Copy this file into the root of your project as CLAUDE.md.
CLAUDE.md
Project
A Next.js 15 App Router application. TypeScript strict. Drizzle ORM for Postgres. Tailwind + shadcn/ui. Deployed to Vercel.
Commands
pnpm dev— http://localhost:3000pnpm buildpnpm typecheckpnpm lintpnpm db:generate— generate SQL from schemapnpm db:migrate— apply migrationspnpm db:studio— Drizzle Studio
Run pnpm typecheck before reporting work complete.
Code style
- Server Components by default. Add
"use client"only when needed (state, effects, browser APIs). - Mutations via Server Actions. Place them in
src/actions/and import where used. - Use Zod for input validation in Server Actions.
- Tailwind only — no CSS modules or styled-components.
- Use the existing
cn()helper fromsrc/lib/utils.ts.
Stack rules
Drizzle
- Schema lives in
src/db/schema.ts. After editing, runpnpm db:generate. - Always use the typed client from
src/db/index.ts. - Prefer relational queries (
db.query.<table>.findMany(…)) for reads. Use the query builder for complex joins. - Every table has a
createdAtandupdatedAt. UsedefaultNow()and a database trigger for updates.
Server Actions
- Files start with
"use server". - Always validate input with Zod before touching the database.
- Throw typed errors via
src/lib/errors.ts. Don't return error strings from actions — throw and let the boundary handle it. - Call
revalidatePath()orrevalidateTag()after mutations. Do not rely on the client to refetch.
UI
- Primitives live in
src/components/ui/(shadcn). Customize tokens intailwind.config.ts, never inline. - Forms via
react-hook-form+@hookform/resolvers/zod, paired with shadcnForm.
Before editing
- Look at sibling files for conventions before introducing a new pattern.
- Read
src/db/schema.tsbefore any data access. - Check
src/components/ui/for an existing primitive before creating one.
Constraints
- Do not introduce a global state library. Use URL state, server state, or
useStatelocally. - Do not use
fetch()from a Client Component to call the same app — use a Server Action. - Do not commit secrets. Use
.env.localand document new vars in.env.example. - Do not write tests for trivial things. Focus on actions, hooks, and integration paths.