Project structure
Where every part of the kit lives, so you know which file to open.
config.ts
proxy.ts
AGENTS.md
.env.example
What each file owns
| Path | What it owns |
|---|---|
src/config.ts | Site name, support email, checkout consent, and the plans you sell |
src/content/landing.ts | Every word on the landing page |
src/components/landing/sections.tsx | Landing page layout (reads landing.ts and plans) |
src/db/schema.ts | Every database table. Auth tables use the field names Better Auth expects |
src/lib/auth.ts | Better Auth config: email and password, social providers, admin plugin, rate limits |
src/lib/session.ts | getSession() and requireUser(): the only way pages read the signed-in user |
src/lib/billing/dodo.ts | All Dodo Payments code: checkout, portal, webhook verification and handling |
src/lib/billing/index.ts | The access rule: getBillingStatus() and getBillingStatuses() |
src/lib/billing/actions.ts | Server actions for checkout and the billing portal |
src/lib/admin.ts | Admin guard (requireAdmin), analytics queries, user list |
src/lib/email.ts | sendEmail() through Resend; prints to the terminal in development without a key |
src/lib/repo-access.ts | Optional GitHub repository delivery |
src/lib/blog.ts, src/content/blog/*.mdx | Blog loader and posts |
src/app/api/webhooks/dodo/route.ts | The Dodo webhook endpoint |
src/proxy.ts | Fast sign-in redirect for /dashboard and /admin (Next.js 16's renamed middleware) |
scripts/setup/ | The npm run setup script |
AGENTS.md | Instructions and rules for AI coding agents |
proxy.ts is not a security check
src/proxy.ts only checks that a session cookie exists, to save a round trip. Every page still checks the user itself with requireUser() or requireAdmin().
Make it yours
Let your AI coding agent turn the example "Acme" site into your product's website, or make the same changes by hand.
How setup works
npm run setup takes a fresh clone to a working app, and optionally a live deployment. This page explains what it does, in what order, and how re-running it works.