P PasteCode
Context Pack

Next.js SaaS Starter — Context Pack

Copyable context pack for a Next.js SaaS app with App Router, Better Auth, Stripe billing, and Postgres so your AI agent works correctly from prompt one.

CursorClaude CodeCodexWindsurf Next.jsPostgreSQLTypeScriptTailwind
.md .json Updated Jun 8, 2026

Paste this at the top of a new task so the agent understands the SaaS project structure, conventions, and boundaries before it writes a single line of code.

Project Background

A multi-tenant SaaS application built with Next.js 15 App Router.
Authentication is handled by Better Auth with email/password and OAuth providers.
Billing uses Stripe Checkout + webhooks. All persistent data lives in PostgreSQL
accessed via Drizzle ORM. The app is deployed to Vercel with a Neon Postgres
database.

Stack

Next.js 15 (App Router, React Server Components)
TypeScript (strict mode, no implicit any)
Tailwind CSS v4
Better Auth v1 (session cookies, OAuth: Google + GitHub)
Drizzle ORM + drizzle-kit migrations
Neon PostgreSQL (serverless driver @neondatabase/serverless)
Stripe (Checkout sessions, Customer Portal, webhooks)
Resend for transactional email
Zod for all input validation

Directory Structure

src/
app/ # App Router — every folder is a route segment
(auth)/ # Sign-in / sign-up pages (unauthenticated layout)
(dashboard)/ # Protected routes (authenticated layout)
billing/
settings/
api/
auth/[...all]/ # Better Auth catch-all handler
webhooks/stripe/ # Stripe webhook endpoint
components/
ui/ # shadcn/ui primitives (do not edit generated files)
app/ # Application-level components
lib/
auth.ts # Better Auth server instance + config
auth-client.ts # Better Auth browser client
db/
schema.ts # Drizzle table definitions (single source of truth)
index.ts # db client (Neon serverless)
stripe.ts # Stripe SDK singleton
validations/ # Zod schemas, one file per domain
middleware.ts # Auth session check + route protection
drizzle/
migrations/ # Auto-generated SQL — never hand-edit
drizzle.config.ts

Coding Conventions

- Server Components by default. Add "use client" only when you need browser
APIs, event handlers, or React hooks.
- Data fetching happens in Server Components or Route Handlers — never
fetch from a Client Component via useEffect.
- Database access only inside lib/db or server actions; never import the db
client into a Client Component.
- All user input is validated with Zod before hitting the database.
- Drizzle schema changes require a migration: `npx drizzle-kit generate` then
`npx drizzle-kit migrate`. Never hand-edit files in drizzle/migrations/.
- API routes live under app/api/ and export named HTTP-method handlers
(GET, POST, etc.). Use NextResponse.json() for responses.
- Environment variables accessed via process.env must also be declared in
.env.example (no secrets in that file).
- Stripe amounts are always in the smallest currency unit (cents).

AI Task Boundaries

- Do not switch the ORM, auth library, or email provider without explicit
instruction.
- Do not edit files under src/components/ui/ — they are shadcn/ui generated
and will be overwritten.
- Do not hard-code secrets. Use process.env and add the key to .env.example.
- Do not add a Pages Router file (pages/ directory). This is App Router only.
- All schema changes must go through Drizzle migrations, not raw SQL ALTER.
- Middleware (middleware.ts) must remain at the project root, not inside src/app.
- Stripe webhook handler must verify the signature with
stripe.webhooks.constructEvent before processing any event.

llms.txt

The repo exposes a /llms.txt at the project root that lists key conventions and file purposes so agents can orient themselves without reading every file.

# Next.js SaaS Starter
Framework: Next.js 15 App Router
Auth: Better Auth (src/lib/auth.ts)
DB: Drizzle ORM + Neon Postgres (src/lib/db/schema.ts)
Billing: Stripe (src/lib/stripe.ts)
Email: Resend
Validation: Zod (src/lib/validations/)
Protected routes: everything under src/app/(dashboard)/
Public routes: src/app/(auth)/ and landing page