Codebase
Codebase Overview
How Creator's codebase is organized and how the pieces fit together.
Architecture
Creator is a Next.js 16 App Router application. Routes are organized into route groups that control access:
| Route Group | Layout | Access |
|---|---|---|
app/(public)/ | Navbar + Footer | Anyone |
app/(protected)/ | Sidebar + Breadcrumbs | Authenticated users only |
app/(protected)/admin/ | Sidebar + Breadcrumbs | Admin role only |
app/auth/ | Centered card | Unauthenticated users only |
app/api/ | None (API routes) | Varies per endpoint |
How route protection works
Route protection is handled by proxy.ts (Next.js middleware). Every route is protected by default — only routes listed in the publicRoutes array (config/public-routes.config.ts) are accessible without authentication.
The proxy handles three cases:
- Unauthenticated users visiting a non-public, non-auth route are redirected to
/auth/loginwith acallbackUrlparameter. - Non-admin users visiting
/adminroutes are redirected to the dashboard. - Authenticated users visiting auth routes (login, signup) are redirected to the dashboard.
API routes add a second layer of protection using requireApiAuth() or requireApiAdmin() from lib/auth/api-guard.ts, which return error responses instead of redirecting.
Key directories
config/ → Centralized configuration (app, billing, routes, menus)
lib/auth/ → NextAuth config, guards, adapter, utilities
lib/db/ → Drizzle schema, database client, query modules
lib/services/ → Email, storage, Stripe, Lemon Squeezy, GitHub
lib/schemas/ → Zod validation schemas
components/ui/ → shadcn/ui components
components/shared/ → Reusable app components (Logo, Footer, Analytics, etc.)
hooks/ → Custom React hooksRequest flow
- User visits a page
proxy.tschecks if the route is public — if not, redirects unauthenticated users to login- Next.js matches the route to a route group
- The page component renders (server component by default)
- Client components hydrate where needed (
"use client"directive)
For API routes:
- Request hits
app/api/[feature]/route.ts - Guard function checks auth (
requireApiAuth()/requireApiAdmin()) - If guard fails, error response is returned immediately
- If guard passes, handler logic runs with the authenticated
userId