Architecture
Project architecture
How a Godspeeds project is organized: the App Router structure, where server and client boundaries fall, and where your own code belongs.
Godspeeds is a Next.js App Router application written in TypeScript and styled with Tailwind CSS. The structure is conventional on purpose — if you know Next.js, nothing here should surprise you.
Directory layout
app/ # Routes, layouts, and server actions
├── (auth)/ # Clerk sign-in and sign-up
├── actions/ # Server actions
├── admin/ # Admin dashboard — users, events
├── api/stripe/ # Stripe endpoints
├── components/ # Route-scoped components
├── dashboard/ # The signed-in application
└── pricing/
components/ # Shared UI
lib/ # Service clients and helpers
convex/ # Schema, queries, mutations, crons, http actions
└── model/ # Shared access-control helpers
middleware.ts # Clerk route protectionServer and client boundaries
Components are server components by default. Reach for "use client" only where you need state, effects, or browser APIs. Keeping the boundary tight is what keeps the client bundle small and the pages fast, which matters for both user experience and search ranking.
Route protection fails closed
middleware.ts lists the routes that are public — the marketing page and the sign-in and sign-up flows — and protects everything else. Adding a new page makes it private by default. You opt routes *out* of protection, never into it, so forgetting a step leaves you locked down rather than exposed.
Where your code goes
- A new page — add a route directory under
app. It is protected by default. - A new API endpoint — add a
route.tsunderapp/api, and guard it as described in Security architecture. - Service clients and helpers —
lib, alongside the Stripe client and analytics helpers already there. - Data and schema — define it in
convex/, covered in Database. - Anything org-scoped — resolve access through
convex/model/orgs.ts; see Organizations and multi-tenancy.