Documentation
These are the files that ship in the repository, rendered as-is. Documentation is per feature, not per release — each guide covers what it does, how to configure it, how it works, how to extend it, and how to remove it cleanly.
Guides
19- ArchitectureNext.js 16 App Router SaaS boilerplate: marketing site, authenticated user app, and an admin panel, sharing one Postgres database and one deploy.
- UI / Design SystemA vendored component library — the code lives in this repo under components/ui/, not a nodemodules black box, matching this starter's "you own it, here's how to remove it" convention — built on shadcn/ui (Base UI-backed, not Radix) on top of a complete CSS-variable token contract (colors, radius, sidebar, chart tokens) with class-based light/dark theming via next-themes, dark by default. Covers the whole site: marketing, auth, the app shell, and the admin area, all sharing the same tokens, primitives, and interaction patterns (confirmation dialogs on every destructive action, Select/Switch/Checkbox instead of native form controls, Table/Badge/Card instead of hand-copied markup).
- SetupGets the app running locally against a real Postgres database, with or without real Google/Stripe credentials.
- AuthenticationEmail/password (with required email verification) and Google OAuth sign-in via better-auth, a user.role column for coarse admin gating, Google-account auto-linking, plus session and account management (active sessions with revoke, linked-provider list, email-confirmed account deletion). Organizations/teams are a separate layer on top — see organizations.md. Site admins additionally get ban/unban and impersonation, covered in its own section below.
- Organizations / TeamsMulti-tenant workspaces on top of better-auth's organization plugin: any user can create an organization, invite members by email with a role (owner/admin/member), and switch between their personal account and any org they belong to. There's no teams layer (nested sub-groups within an org) — just flat orgs with roles. Turn that on later via the teams plugin option if a project needs it.
- BillingThree-tier recurring subscriptions (Free / Pro / Business, monthly or annual) via Stripe, driven entirely by @better-auth/stripe: checkout, a self-serve billing portal, invoices, promo codes, optional free trials, optional automatic tax, webhook idempotency, and a payment-failure (dunning) banner.
- Transactional EmailSends verification, password-reset, welcome, and subscription-lifecycle emails via Resend, rendered with React Email components. Email is now required to complete signup — requireEmailVerification: true blocks sign-in until the address is verified.
- Testing & CIVitest for unit and integration tests, Playwright for end-to-end browser tests, all run on every push/PR by a GitHub Actions workflow (lint → typecheck → unit tests → build, plus parallel DB-backed integration and Playwright jobs).
- Security & HardeningRate limiting (better-auth's own endpoints, plus our own Server Actions), security response headers (CSP report-only, HSTS, frame/referrer/permissions policy), optional Cloudflare Turnstile bot-checks on signup and the contact form, and an admin-visible audit log of sensitive account/org/billing actions.
- File UploadsPresigned, direct-to-S3 uploads/downloads for three use cases: your own avatar, an organization's logo, and a shared shelf of private "org documents" any member can upload to. No file ever passes through the Next.js server — the browser PUTs straight to S3 (or a local MinIO container), and every download goes through a stable /api/files/{id} URL that redirects to a freshly-minted, short-lived presigned GET.
- NotificationsA generalized dispatcher for "tell a user something happened" — always writes an in-app notification (the bell in the app header), and optionally also sends an email, gated by a per-user preference the user controls themselves in /settings.
- Feature FlagsDB-backed boolean flags — no third-party flag service. An admin toggles a flag at /admin/flags; the app checks it with getFlag(key, default) and behavior changes on the very next request, no deploy.
- Content (Blog / Changelog / Legal)A file-based MDX content system shared by three collections: the blog (/blog), the changelog (/changelog), and legal pages (/legal/[slug]). No CMS, no database table — content lives in the repo as .mdx files with frontmatter, versioned and reviewed like code.
- AI-Ready ModuleA thin, reusable wrapper around the Anthropic SDK (lib/ai.ts) plus one worked example built on top of it: an "Improve with AI" button on the contact form that rewrites a visitor's rough draft into a clearer message. Every call is logged to an aiusage table with token counts and an estimated USD cost, and the feature is gated behind both a configured API key and a feature flag — see feature-flags.md.
- Public API & API KeysA versioned /api/v1 route group, authenticated via a Bearer API key instead of the session cookie every other route uses. Users create/revoke their own keys at /settings/api-keys; each key is scoped to that user (not an organization) and per-key rate-limited by better-auth's own @better-auth/api-key plugin.
- Outbound WebhooksLets a user register their own webhook URL(s) at /settings/webhooks, subscribe each to specific event types, and see a delivery log — status, attempt count, HTTP response code, last error — with a manual "Redeliver" button per failed row. Every delivery is HMAC-signed so the receiving end can verify it actually came from this app.
- ObservabilityThree independent, individually-optional pieces:
- DeploymentTwo supported production targets — Vercel (zero-config) and a plain Docker/VPS target via output: "standalone" — plus scripts/setup.ts, the interactive CLI that takes a fresh clone to a running, seeded local app in one command (see setup.md for the local-dev side of that; this doc covers what changes for a real deployment).
- Public demo modeTurns one deployment of this kit into a demo anyone can click through without signing up: two shared accounts behind one-click buttons on /login, a banner on every page saying what this is, seeded data so no screen is empty, and a set of guardrails so the first visitor can't break it for the second.
Recipes
5Task-oriented, for when you already know what you want to do.