Next.js SaaS
App Router, Postgres, Stripe and auth. The most common indie SaaS setup.
CLAUDE.md: Next.js SaaS
# Invoice chaser A SaaS that emails polite payment reminders for overdue freelance invoices. Read docs/PRD.md before planning. Build only what is in its MVP scope. ## Commands - Install: `pnpm install` - Dev server: `pnpm dev` (http://localhost:3000) - Test: `pnpm test` - Lint and typecheck: `pnpm lint && pnpm tsc --noEmit` - DB migration: `pnpm db:migrate` (never edit a migration that has already run) ## Structure - `app/`: routes (App Router). Server components by default. - `app/api/`: route handlers. Webhooks live in `app/api/webhooks/`. - `lib/db.ts`: the only database client. Import it; don't create another. - `lib/stripe.ts`: Stripe client and price IDs. - `emails/`: email templates. ## Conventions - TypeScript strict. No `any`. - Add `"use client"` only to components that need state or browser APIs. - Validate every request body with zod before it touches the database. - Money is stored in cents as integers. ## Rules - Run lint, typecheck and tests before saying a task is done. - Ask before adding a dependency. - Verify the Stripe signature on every webhook before reading the payload. - Never commit secrets. Env vars live in `.env.local`, documented in `.env.example`. ## Gotchas - Stripe can send the same webhook event more than once. Handlers must be idempotent (check the event ID).
- "The only database client" stops the agent from creating a second connection pool in a new file.
- Money in cents and idempotent webhooks are the two bugs agents write most often in billing code.
- The migration rule protects the one kind of file you can't safely regenerate.