Architecture overview
How auth, billing, the database, jobs, and the compliance primitives fit together — and where the seams are.
The shape of the app
The boilerplate is a single Next.js 16 App Router project with three top- level surface kinds:
| Surface | Route group | Owner |
|---|---|---|
| Marketing | src/app/[locale]/(marketing)/ | landing-page-ui skill |
| Operational | src/app/[locale]/(auth)/dashboard/ | dashboard-ui skill |
| Public APIs | src/app/api/ | cross-cutting |
Plus the docs site you're reading at src/app/docs/ (non-localized — sales
surface stays English-only).
Internationalization (next-intl) is wrapped around the app surfaces only;
infrastructure routes (/api/*, /docs/*, /.well-known/*) are exempt.
Layers
┌──────────────────────────────────────────────────────────┐
│ Routes (App Router) │
│ src/app/... │
└──────────────────────────────────────────────────────────┘
│ thin handlers, server components
▼
┌──────────────────────────────────────────────────────────┐
│ Server actions (src/actions/*) │
│ Validation (zod) → role gate → call lib → revalidatePath│
└──────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────┐
│ Libraries (src/libs/*) │
│ AuditChain, Email, Idempotency, Llm, Prompts, │
│ Storage, Tier, Webhooks, Status, Evidence, ... │
└──────────────────────────────────────────────────────────┘
│ Drizzle queries, never raw SQL
▼
┌──────────────────────────────────────────────────────────┐
│ Schema (src/models/Schema.ts) → migrations/ │
└──────────────────────────────────────────────────────────┘Routes are thin. Server actions are the real public surface. Libraries
encapsulate the integration with each external system. The database layer is
schema-driven — every table change goes through npm run db:generate and lands
as a numbered migration in migrations/.
Cross-cutting subsystems
- Auth — currently NextAuth v5 beta + Drizzle adapter. Migration to Better Auth is on the roadmap.
- Billing — Stripe Checkout + webhooks today; Paddle / Polar adapters planned (architecture/billing).
- Database — Drizzle ORM, PGlite local, Postgres prod (architecture/database).
- Jobs — adapter-neutral scheduled jobs registered in
src/jobs/registry.ts. Local, Railway, Cloudflare Queues, or Trigger.dev providers can dispatch them. - Audit chain — append-only hash chain, see compliance.
- Idempotency —
Idempotency-Keycontract for any mutating route. - LLM cost — usage ledger, budgets, versioned prompts. Money is always integer cents.
What you don't have to build
- A bespoke audit-log table.
- A custom webhook fan-out + replay queue.
- A "download my data" pipeline.
- A 30-day grace deletion window.
- A status page.
- A maintenance mode.
- A document-packet exporter (PDF + DOCX, format-agnostic registry).
- A saved-views primitive for filter bars.
- A tier-gate component.
Everything above is wired, documented in CLAUDE.md, and has a rollback
recipe.
Customizing the boilerplate
Design tokens (Tailwind v4), adding a locale to next-intl, swapping the payment provider (Stripe → Polar / Paddle), and the branding placeholders to swap on day one.
Authentication — NextAuth → Better Auth migration plan
Why we ship with NextAuth today, why we're moving to Better Auth, and the migration path that won't lock you in.