Next.js + Drizzle + Clerk rules for AI coding agents
Full stack: Next.js (App Router) + Tailwind CSS v4 + Drizzle ORM + Clerk auth + Zod validation
Ready-to-commit rules for Next.js (App Router) + Tailwind CSS v4 + Drizzle ORM + Clerk auth + Zod validation in every major format: AGENTS.md (Codex, Cursor, Copilot), CLAUDE.md (Claude Code), Cursor .mdc project rules, legacy .cursorrules, Copilot instructions, Windsurf rules and GEMINI.md. Next.js with Clerk for auth and Drizzle ORM on Postgres: fast to build, type-safe end to end.
Last reviewed 2026-10-21 · Customise in the generator · Raw: AGENTS.md, CLAUDE.md
Agents protect pages in middleware but forget to check `userId` inside Server Actions, which are public endpoints.
Generated files
# AGENTS.md - this project
Instructions for AI coding agents working in this repository.
## Project
A Next.js (App Router) + Tailwind CSS v4 + Drizzle ORM + Clerk auth + Zod validation project.
Stack: Next.js (App Router), Tailwind CSS v4, Drizzle ORM, Clerk auth, Zod validation.
## Commands
- Dev server: `npm run dev`
- Production build (also type-checks): `npm run build`
- Lint: `npm run lint`
- Generate migration: `npx drizzle-kit generate`
- Apply migrations: `npx drizzle-kit migrate`
## Project structure
- `app/` holds routes: `page.tsx`, `layout.tsx`, `loading.tsx`, `error.tsx`, `route.ts` for API handlers.
- Shared UI in `components/`, server-only helpers in `lib/` (mark them with `import "server-only"`).
## How to work in this repo
- Read the relevant files before editing. Follow the patterns already in the codebase over these generic rules.
- Make the smallest change that solves the task. Do not refactor or reformat unrelated code.
- Before saying a task is done, run the type-check, lint and tests listed under Commands and fix what you broke.
- If requirements are ambiguous, ask one clear question instead of guessing.
- Never commit secrets, API keys or `.env` files. Use env vars and keep `.env.example` up to date.
- Do not add a new dependency when the standard library or an existing dependency already covers it.
- Ask before adding, removing or upgrading any dependency.
- Ask before changing database schemas, auth, payments or CI configuration.
- Never delete files, drop data or run destructive commands (`rm -rf`, `git push --force`, `DROP TABLE`) without explicit approval.
- Keep each change under ~200 changed lines where possible; split larger work into steps.
## Next.js (App Router)
- Check the Next.js major version in `package.json` before using an API; follow the docs for that version.
- Components are Server Components by default. Add `"use client"` only to the smallest leaf component that needs state, effects, or browser APIs.
- Fetch data in Server Components or Server Actions, not in `useEffect`.
- In Next.js 15+, `params`, `searchParams`, `cookies()` and `headers()` are async: always `await` them.
- Mutations go through Server Actions (`"use server"`) or `route.ts` handlers. Validate every input on the server and re-check auth inside the action.
- After a mutation, call `revalidatePath()` or `revalidateTag()` instead of forcing the whole route dynamic.
- Use `next/image` for images, `next/font` for fonts and `next/link` for internal links.
- Export `metadata` or `generateMetadata` from every page for title, description and Open Graph tags.
- Only variables prefixed `NEXT_PUBLIC_` reach the browser. Never put secrets in them.
- In Next.js 16, `middleware.ts` is renamed `proxy.ts`. Use whichever file the project already has.
## Tailwind CSS v4
- Tailwind v4 is configured in CSS: `@import "tailwindcss";` plus `@theme { ... }` for design tokens. Do not create a `tailwind.config.js` unless the project already has one.
- Use theme tokens (colors, spacing) instead of arbitrary values like `w-[37px]`.
- Build responsive layouts mobile-first with `sm:`, `md:`, `lg:` prefixes.
- Extract repeated class lists into components, not `@apply` chains.
- Support dark mode with the `dark:` variant when the project uses it.
## Drizzle ORM
- Schema lives in TypeScript (`db/schema.ts`). Generate SQL migrations with `drizzle-kit generate` and commit them.
- `drizzle-kit push` is for local prototyping only, never for production databases.
- Infer types with `typeof table.$inferSelect` / `$inferInsert` instead of duplicating interfaces.
- Use the query builder or `sql` template tag; never build SQL with string concatenation.
- Use `db.transaction()` for multi-step writes.
## Clerk auth
- Protect routes with `clerkMiddleware()` and `createRouteMatcher` in the middleware/proxy file.
- On the server use `await auth()` / `await currentUser()` from `@clerk/nextjs/server`, and check `userId` in every Server Action and route handler.
- Use Clerk components (`<SignIn />`, `<UserButton />`) rather than hand-built auth forms.
- `CLERK_SECRET_KEY` is server-only; only the publishable key may be public.
## Zod validation
- Validate all untrusted input (request bodies, form data, env vars, third-party API responses) with a Zod schema at the boundary.
- Derive TypeScript types from schemas with `z.infer<typeof schema>`; do not hand-write duplicate types.
- Use `safeParse` where you need to return validation errors to the user.
## Avoid
- Do not add `"use client"` to layouts or pages just to silence an error; move the interactive part into a child component.
- Do not use the Pages Router (`pages/`) APIs such as `getServerSideProps` in an App Router project.
## Reference docs
- [Next.js docs](https://nextjs.org/docs)
- [Tailwind CSS docs](https://tailwindcss.com/docs)
- [Drizzle docs](https://orm.drizzle.team/docs/overview)
- [Clerk docs](https://clerk.com/docs)
- [Zod docs](https://zod.dev)
# CLAUDE.md - this project
Project instructions for Claude Code.
## Project
A Next.js (App Router) + Tailwind CSS v4 + Drizzle ORM + Clerk auth + Zod validation project.
Stack: Next.js (App Router), Tailwind CSS v4, Drizzle ORM, Clerk auth, Zod validation.
## Commands
- Dev server: `npm run dev`
- Production build (also type-checks): `npm run build`
- Lint: `npm run lint`
- Generate migration: `npx drizzle-kit generate`
- Apply migrations: `npx drizzle-kit migrate`
## Project structure
- `app/` holds routes: `page.tsx`, `layout.tsx`, `loading.tsx`, `error.tsx`, `route.ts` for API handlers.
- Shared UI in `components/`, server-only helpers in `lib/` (mark them with `import "server-only"`).
## How to work in this repo
- Read the relevant files before editing. Follow the patterns already in the codebase over these generic rules.
- Make the smallest change that solves the task. Do not refactor or reformat unrelated code.
- Before saying a task is done, run the type-check, lint and tests listed under Commands and fix what you broke.
- If requirements are ambiguous, ask one clear question instead of guessing.
- Never commit secrets, API keys or `.env` files. Use env vars and keep `.env.example` up to date.
- Do not add a new dependency when the standard library or an existing dependency already covers it.
- Ask before adding, removing or upgrading any dependency.
- Ask before changing database schemas, auth, payments or CI configuration.
- Never delete files, drop data or run destructive commands (`rm -rf`, `git push --force`, `DROP TABLE`) without explicit approval.
- Keep each change under ~200 changed lines where possible; split larger work into steps.
## Next.js (App Router)
- Check the Next.js major version in `package.json` before using an API; follow the docs for that version.
- Components are Server Components by default. Add `"use client"` only to the smallest leaf component that needs state, effects, or browser APIs.
- Fetch data in Server Components or Server Actions, not in `useEffect`.
- In Next.js 15+, `params`, `searchParams`, `cookies()` and `headers()` are async: always `await` them.
- Mutations go through Server Actions (`"use server"`) or `route.ts` handlers. Validate every input on the server and re-check auth inside the action.
- After a mutation, call `revalidatePath()` or `revalidateTag()` instead of forcing the whole route dynamic.
- Use `next/image` for images, `next/font` for fonts and `next/link` for internal links.
- Export `metadata` or `generateMetadata` from every page for title, description and Open Graph tags.
- Only variables prefixed `NEXT_PUBLIC_` reach the browser. Never put secrets in them.
- In Next.js 16, `middleware.ts` is renamed `proxy.ts`. Use whichever file the project already has.
## Tailwind CSS v4
- Tailwind v4 is configured in CSS: `@import "tailwindcss";` plus `@theme { ... }` for design tokens. Do not create a `tailwind.config.js` unless the project already has one.
- Use theme tokens (colors, spacing) instead of arbitrary values like `w-[37px]`.
- Build responsive layouts mobile-first with `sm:`, `md:`, `lg:` prefixes.
- Extract repeated class lists into components, not `@apply` chains.
- Support dark mode with the `dark:` variant when the project uses it.
## Drizzle ORM
- Schema lives in TypeScript (`db/schema.ts`). Generate SQL migrations with `drizzle-kit generate` and commit them.
- `drizzle-kit push` is for local prototyping only, never for production databases.
- Infer types with `typeof table.$inferSelect` / `$inferInsert` instead of duplicating interfaces.
- Use the query builder or `sql` template tag; never build SQL with string concatenation.
- Use `db.transaction()` for multi-step writes.
## Clerk auth
- Protect routes with `clerkMiddleware()` and `createRouteMatcher` in the middleware/proxy file.
- On the server use `await auth()` / `await currentUser()` from `@clerk/nextjs/server`, and check `userId` in every Server Action and route handler.
- Use Clerk components (`<SignIn />`, `<UserButton />`) rather than hand-built auth forms.
- `CLERK_SECRET_KEY` is server-only; only the publishable key may be public.
## Zod validation
- Validate all untrusted input (request bodies, form data, env vars, third-party API responses) with a Zod schema at the boundary.
- Derive TypeScript types from schemas with `z.infer<typeof schema>`; do not hand-write duplicate types.
- Use `safeParse` where you need to return validation errors to the user.
## Avoid
- Do not add `"use client"` to layouts or pages just to silence an error; move the interactive part into a child component.
- Do not use the Pages Router (`pages/`) APIs such as `getServerSideProps` in an App Router project.
## Reference docs
- [Next.js docs](https://nextjs.org/docs)
- [Tailwind CSS docs](https://tailwindcss.com/docs)
- [Drizzle docs](https://orm.drizzle.team/docs/overview)
- [Clerk docs](https://clerk.com/docs)
- [Zod docs](https://zod.dev)
---
description: "Core rules for this project"
alwaysApply: true
---
# this project
A Next.js (App Router) + Tailwind CSS v4 + Drizzle ORM + Clerk auth + Zod validation project.
Stack: Next.js (App Router), Tailwind CSS v4, Drizzle ORM, Clerk auth, Zod validation.
## Commands
- Dev server: `npm run dev`
- Production build (also type-checks): `npm run build`
- Lint: `npm run lint`
- Generate migration: `npx drizzle-kit generate`
- Apply migrations: `npx drizzle-kit migrate`
## How to work in this repo
- Read the relevant files before editing. Follow the patterns already in the codebase over these generic rules.
- Make the smallest change that solves the task. Do not refactor or reformat unrelated code.
- Before saying a task is done, run the type-check, lint and tests listed under Commands and fix what you broke.
- If requirements are ambiguous, ask one clear question instead of guessing.
- Never commit secrets, API keys or `.env` files. Use env vars and keep `.env.example` up to date.
- Do not add a new dependency when the standard library or an existing dependency already covers it.
- Ask before adding, removing or upgrading any dependency.
- Ask before changing database schemas, auth, payments or CI configuration.
- Never delete files, drop data or run destructive commands (`rm -rf`, `git push --force`, `DROP TABLE`) without explicit approval.
- Keep each change under ~200 changed lines where possible; split larger work into steps.
---
description: "Next.js (App Router) conventions: Next.js App Router with React Server Components and TypeScript."
globs: app/**/*.tsx, app/**/*.ts, src/**/*.tsx, src/**/*.ts
alwaysApply: false
---
# Next.js (App Router)
- Check the Next.js major version in `package.json` before using an API; follow the docs for that version.
- Components are Server Components by default. Add `"use client"` only to the smallest leaf component that needs state, effects, or browser APIs.
- Fetch data in Server Components or Server Actions, not in `useEffect`.
- In Next.js 15+, `params`, `searchParams`, `cookies()` and `headers()` are async: always `await` them.
- Mutations go through Server Actions (`"use server"`) or `route.ts` handlers. Validate every input on the server and re-check auth inside the action.
- After a mutation, call `revalidatePath()` or `revalidateTag()` instead of forcing the whole route dynamic.
- Use `next/image` for images, `next/font` for fonts and `next/link` for internal links.
- Export `metadata` or `generateMetadata` from every page for title, description and Open Graph tags.
- Only variables prefixed `NEXT_PUBLIC_` reach the browser. Never put secrets in them.
- In Next.js 16, `middleware.ts` is renamed `proxy.ts`. Use whichever file the project already has.
## Avoid
- Do not add `"use client"` to layouts or pages just to silence an error; move the interactive part into a child component.
- Do not use the Pages Router (`pages/`) APIs such as `getServerSideProps` in an App Router project.
Docs: https://nextjs.org/docs
---
description: "Tailwind CSS v4 conventions: Utility-first styling with Tailwind CSS v4."
globs: **/*.css, **/*.tsx, **/*.vue, **/*.svelte, **/*.astro, **/*.html, **/*.blade.php, **/*.erb
alwaysApply: false
---
# Tailwind CSS v4
- Tailwind v4 is configured in CSS: `@import "tailwindcss";` plus `@theme { ... }` for design tokens. Do not create a `tailwind.config.js` unless the project already has one.
- Use theme tokens (colors, spacing) instead of arbitrary values like `w-[37px]`.
- Build responsive layouts mobile-first with `sm:`, `md:`, `lg:` prefixes.
- Extract repeated class lists into components, not `@apply` chains.
- Support dark mode with the `dark:` variant when the project uses it.
Docs: https://tailwindcss.com/docs
---
description: "Drizzle ORM conventions: SQL-like TypeScript ORM with drizzle-kit migrations."
globs: db/**/*.ts, src/db/**/*.ts, drizzle/**
alwaysApply: false
---
# Drizzle ORM
- Schema lives in TypeScript (`db/schema.ts`). Generate SQL migrations with `drizzle-kit generate` and commit them.
- `drizzle-kit push` is for local prototyping only, never for production databases.
- Infer types with `typeof table.$inferSelect` / `$inferInsert` instead of duplicating interfaces.
- Use the query builder or `sql` template tag; never build SQL with string concatenation.
- Use `db.transaction()` for multi-step writes.
Docs: https://orm.drizzle.team/docs/overview
---
description: "Clerk auth conventions: Authentication and user management with Clerk."
globs: middleware.ts, proxy.ts, app/**/*.tsx
alwaysApply: false
---
# Clerk auth
- Protect routes with `clerkMiddleware()` and `createRouteMatcher` in the middleware/proxy file.
- On the server use `await auth()` / `await currentUser()` from `@clerk/nextjs/server`, and check `userId` in every Server Action and route handler.
- Use Clerk components (`<SignIn />`, `<UserButton />`) rather than hand-built auth forms.
- `CLERK_SECRET_KEY` is server-only; only the publishable key may be public.
Docs: https://clerk.com/docs
---
description: "Zod validation conventions: Runtime schema validation with Zod."
globs: **/*.ts, **/*.tsx
alwaysApply: false
---
# Zod validation
- Validate all untrusted input (request bodies, form data, env vars, third-party API responses) with a Zod schema at the boundary.
- Derive TypeScript types from schemas with `z.infer<typeof schema>`; do not hand-write duplicate types.
- Use `safeParse` where you need to return validation errors to the user.
Docs: https://zod.dev
# Cursor rules - this project
You are an expert Next.js (App Router), Tailwind CSS v4, Drizzle ORM, Clerk auth, Zod validation engineer working on this codebase. Follow these rules.
## Project
A Next.js (App Router) + Tailwind CSS v4 + Drizzle ORM + Clerk auth + Zod validation project.
Stack: Next.js (App Router), Tailwind CSS v4, Drizzle ORM, Clerk auth, Zod validation.
## Commands
- Dev server: `npm run dev`
- Production build (also type-checks): `npm run build`
- Lint: `npm run lint`
- Generate migration: `npx drizzle-kit generate`
- Apply migrations: `npx drizzle-kit migrate`
## Project structure
- `app/` holds routes: `page.tsx`, `layout.tsx`, `loading.tsx`, `error.tsx`, `route.ts` for API handlers.
- Shared UI in `components/`, server-only helpers in `lib/` (mark them with `import "server-only"`).
## How to work in this repo
- Read the relevant files before editing. Follow the patterns already in the codebase over these generic rules.
- Make the smallest change that solves the task. Do not refactor or reformat unrelated code.
- Before saying a task is done, run the type-check, lint and tests listed under Commands and fix what you broke.
- If requirements are ambiguous, ask one clear question instead of guessing.
- Never commit secrets, API keys or `.env` files. Use env vars and keep `.env.example` up to date.
- Do not add a new dependency when the standard library or an existing dependency already covers it.
- Ask before adding, removing or upgrading any dependency.
- Ask before changing database schemas, auth, payments or CI configuration.
- Never delete files, drop data or run destructive commands (`rm -rf`, `git push --force`, `DROP TABLE`) without explicit approval.
- Keep each change under ~200 changed lines where possible; split larger work into steps.
## Next.js (App Router)
- Check the Next.js major version in `package.json` before using an API; follow the docs for that version.
- Components are Server Components by default. Add `"use client"` only to the smallest leaf component that needs state, effects, or browser APIs.
- Fetch data in Server Components or Server Actions, not in `useEffect`.
- In Next.js 15+, `params`, `searchParams`, `cookies()` and `headers()` are async: always `await` them.
- Mutations go through Server Actions (`"use server"`) or `route.ts` handlers. Validate every input on the server and re-check auth inside the action.
- After a mutation, call `revalidatePath()` or `revalidateTag()` instead of forcing the whole route dynamic.
- Use `next/image` for images, `next/font` for fonts and `next/link` for internal links.
- Export `metadata` or `generateMetadata` from every page for title, description and Open Graph tags.
- Only variables prefixed `NEXT_PUBLIC_` reach the browser. Never put secrets in them.
- In Next.js 16, `middleware.ts` is renamed `proxy.ts`. Use whichever file the project already has.
## Tailwind CSS v4
- Tailwind v4 is configured in CSS: `@import "tailwindcss";` plus `@theme { ... }` for design tokens. Do not create a `tailwind.config.js` unless the project already has one.
- Use theme tokens (colors, spacing) instead of arbitrary values like `w-[37px]`.
- Build responsive layouts mobile-first with `sm:`, `md:`, `lg:` prefixes.
- Extract repeated class lists into components, not `@apply` chains.
- Support dark mode with the `dark:` variant when the project uses it.
## Drizzle ORM
- Schema lives in TypeScript (`db/schema.ts`). Generate SQL migrations with `drizzle-kit generate` and commit them.
- `drizzle-kit push` is for local prototyping only, never for production databases.
- Infer types with `typeof table.$inferSelect` / `$inferInsert` instead of duplicating interfaces.
- Use the query builder or `sql` template tag; never build SQL with string concatenation.
- Use `db.transaction()` for multi-step writes.
## Clerk auth
- Protect routes with `clerkMiddleware()` and `createRouteMatcher` in the middleware/proxy file.
- On the server use `await auth()` / `await currentUser()` from `@clerk/nextjs/server`, and check `userId` in every Server Action and route handler.
- Use Clerk components (`<SignIn />`, `<UserButton />`) rather than hand-built auth forms.
- `CLERK_SECRET_KEY` is server-only; only the publishable key may be public.
## Zod validation
- Validate all untrusted input (request bodies, form data, env vars, third-party API responses) with a Zod schema at the boundary.
- Derive TypeScript types from schemas with `z.infer<typeof schema>`; do not hand-write duplicate types.
- Use `safeParse` where you need to return validation errors to the user.
## Avoid
- Do not add `"use client"` to layouts or pages just to silence an error; move the interactive part into a child component.
- Do not use the Pages Router (`pages/`) APIs such as `getServerSideProps` in an App Router project.
## Reference docs
- [Next.js docs](https://nextjs.org/docs)
- [Tailwind CSS docs](https://tailwindcss.com/docs)
- [Drizzle docs](https://orm.drizzle.team/docs/overview)
- [Clerk docs](https://clerk.com/docs)
- [Zod docs](https://zod.dev)
# Copilot instructions - this project
A Next.js (App Router) + Tailwind CSS v4 + Drizzle ORM + Clerk auth + Zod validation project.
Stack: Next.js (App Router), Tailwind CSS v4, Drizzle ORM, Clerk auth, Zod validation.
## Commands
- Dev server: `npm run dev`
- Production build (also type-checks): `npm run build`
- Lint: `npm run lint`
- Generate migration: `npx drizzle-kit generate`
- Apply migrations: `npx drizzle-kit migrate`
## How to work in this repo
- Read the relevant files before editing. Follow the patterns already in the codebase over these generic rules.
- Make the smallest change that solves the task. Do not refactor or reformat unrelated code.
- Before saying a task is done, run the type-check, lint and tests listed under Commands and fix what you broke.
- If requirements are ambiguous, ask one clear question instead of guessing.
- Never commit secrets, API keys or `.env` files. Use env vars and keep `.env.example` up to date.
- Do not add a new dependency when the standard library or an existing dependency already covers it.
- Ask before adding, removing or upgrading any dependency.
- Ask before changing database schemas, auth, payments or CI configuration.
- Never delete files, drop data or run destructive commands (`rm -rf`, `git push --force`, `DROP TABLE`) without explicit approval.
- Keep each change under ~200 changed lines where possible; split larger work into steps.
---
applyTo: "app/**/*.tsx,app/**/*.ts,src/**/*.tsx,src/**/*.ts"
---
# Next.js (App Router)
- Check the Next.js major version in `package.json` before using an API; follow the docs for that version.
- Components are Server Components by default. Add `"use client"` only to the smallest leaf component that needs state, effects, or browser APIs.
- Fetch data in Server Components or Server Actions, not in `useEffect`.
- In Next.js 15+, `params`, `searchParams`, `cookies()` and `headers()` are async: always `await` them.
- Mutations go through Server Actions (`"use server"`) or `route.ts` handlers. Validate every input on the server and re-check auth inside the action.
- After a mutation, call `revalidatePath()` or `revalidateTag()` instead of forcing the whole route dynamic.
- Use `next/image` for images, `next/font` for fonts and `next/link` for internal links.
- Export `metadata` or `generateMetadata` from every page for title, description and Open Graph tags.
- Only variables prefixed `NEXT_PUBLIC_` reach the browser. Never put secrets in them.
- In Next.js 16, `middleware.ts` is renamed `proxy.ts`. Use whichever file the project already has.
---
applyTo: "**/*.css,**/*.tsx,**/*.vue,**/*.svelte,**/*.astro,**/*.html,**/*.blade.php,**/*.erb"
---
# Tailwind CSS v4
- Tailwind v4 is configured in CSS: `@import "tailwindcss";` plus `@theme { ... }` for design tokens. Do not create a `tailwind.config.js` unless the project already has one.
- Use theme tokens (colors, spacing) instead of arbitrary values like `w-[37px]`.
- Build responsive layouts mobile-first with `sm:`, `md:`, `lg:` prefixes.
- Extract repeated class lists into components, not `@apply` chains.
- Support dark mode with the `dark:` variant when the project uses it.
---
applyTo: "db/**/*.ts,src/db/**/*.ts,drizzle/**"
---
# Drizzle ORM
- Schema lives in TypeScript (`db/schema.ts`). Generate SQL migrations with `drizzle-kit generate` and commit them.
- `drizzle-kit push` is for local prototyping only, never for production databases.
- Infer types with `typeof table.$inferSelect` / `$inferInsert` instead of duplicating interfaces.
- Use the query builder or `sql` template tag; never build SQL with string concatenation.
- Use `db.transaction()` for multi-step writes.
---
applyTo: "middleware.ts,proxy.ts,app/**/*.tsx"
---
# Clerk auth
- Protect routes with `clerkMiddleware()` and `createRouteMatcher` in the middleware/proxy file.
- On the server use `await auth()` / `await currentUser()` from `@clerk/nextjs/server`, and check `userId` in every Server Action and route handler.
- Use Clerk components (`<SignIn />`, `<UserButton />`) rather than hand-built auth forms.
- `CLERK_SECRET_KEY` is server-only; only the publishable key may be public.
---
applyTo: "**/*.ts,**/*.tsx"
---
# Zod validation
- Validate all untrusted input (request bodies, form data, env vars, third-party API responses) with a Zod schema at the boundary.
- Derive TypeScript types from schemas with `z.infer<typeof schema>`; do not hand-write duplicate types.
- Use `safeParse` where you need to return validation errors to the user.
---
trigger: always_on
---
# this project
A Next.js (App Router) + Tailwind CSS v4 + Drizzle ORM + Clerk auth + Zod validation project.
Stack: Next.js (App Router), Tailwind CSS v4, Drizzle ORM, Clerk auth, Zod validation.
## Commands
- Dev server: `npm run dev`
- Production build (also type-checks): `npm run build`
- Lint: `npm run lint`
- Generate migration: `npx drizzle-kit generate`
- Apply migrations: `npx drizzle-kit migrate`
## How to work in this repo
- Read the relevant files before editing. Follow the patterns already in the codebase over these generic rules.
- Make the smallest change that solves the task. Do not refactor or reformat unrelated code.
- Before saying a task is done, run the type-check, lint and tests listed under Commands and fix what you broke.
- If requirements are ambiguous, ask one clear question instead of guessing.
- Never commit secrets, API keys or `.env` files. Use env vars and keep `.env.example` up to date.
- Do not add a new dependency when the standard library or an existing dependency already covers it.
- Ask before adding, removing or upgrading any dependency.
- Ask before changing database schemas, auth, payments or CI configuration.
- Never delete files, drop data or run destructive commands (`rm -rf`, `git push --force`, `DROP TABLE`) without explicit approval.
- Keep each change under ~200 changed lines where possible; split larger work into steps.
---
trigger: glob
globs: app/**/*.tsx, app/**/*.ts, src/**/*.tsx, src/**/*.ts
---
# Next.js (App Router)
- Check the Next.js major version in `package.json` before using an API; follow the docs for that version.
- Components are Server Components by default. Add `"use client"` only to the smallest leaf component that needs state, effects, or browser APIs.
- Fetch data in Server Components or Server Actions, not in `useEffect`.
- In Next.js 15+, `params`, `searchParams`, `cookies()` and `headers()` are async: always `await` them.
- Mutations go through Server Actions (`"use server"`) or `route.ts` handlers. Validate every input on the server and re-check auth inside the action.
- After a mutation, call `revalidatePath()` or `revalidateTag()` instead of forcing the whole route dynamic.
- Use `next/image` for images, `next/font` for fonts and `next/link` for internal links.
- Export `metadata` or `generateMetadata` from every page for title, description and Open Graph tags.
- Only variables prefixed `NEXT_PUBLIC_` reach the browser. Never put secrets in them.
- In Next.js 16, `middleware.ts` is renamed `proxy.ts`. Use whichever file the project already has.
---
trigger: glob
globs: **/*.css, **/*.tsx, **/*.vue, **/*.svelte, **/*.astro, **/*.html, **/*.blade.php, **/*.erb
---
# Tailwind CSS v4
- Tailwind v4 is configured in CSS: `@import "tailwindcss";` plus `@theme { ... }` for design tokens. Do not create a `tailwind.config.js` unless the project already has one.
- Use theme tokens (colors, spacing) instead of arbitrary values like `w-[37px]`.
- Build responsive layouts mobile-first with `sm:`, `md:`, `lg:` prefixes.
- Extract repeated class lists into components, not `@apply` chains.
- Support dark mode with the `dark:` variant when the project uses it.
---
trigger: glob
globs: db/**/*.ts, src/db/**/*.ts, drizzle/**
---
# Drizzle ORM
- Schema lives in TypeScript (`db/schema.ts`). Generate SQL migrations with `drizzle-kit generate` and commit them.
- `drizzle-kit push` is for local prototyping only, never for production databases.
- Infer types with `typeof table.$inferSelect` / `$inferInsert` instead of duplicating interfaces.
- Use the query builder or `sql` template tag; never build SQL with string concatenation.
- Use `db.transaction()` for multi-step writes.
---
trigger: glob
globs: middleware.ts, proxy.ts, app/**/*.tsx
---
# Clerk auth
- Protect routes with `clerkMiddleware()` and `createRouteMatcher` in the middleware/proxy file.
- On the server use `await auth()` / `await currentUser()` from `@clerk/nextjs/server`, and check `userId` in every Server Action and route handler.
- Use Clerk components (`<SignIn />`, `<UserButton />`) rather than hand-built auth forms.
- `CLERK_SECRET_KEY` is server-only; only the publishable key may be public.
---
trigger: glob
globs: **/*.ts, **/*.tsx
---
# Zod validation
- Validate all untrusted input (request bodies, form data, env vars, third-party API responses) with a Zod schema at the boundary.
- Derive TypeScript types from schemas with `z.infer<typeof schema>`; do not hand-write duplicate types.
- Use `safeParse` where you need to return validation errors to the user.
# GEMINI.md - this project
Project context for Gemini CLI.
## Project
A Next.js (App Router) + Tailwind CSS v4 + Drizzle ORM + Clerk auth + Zod validation project.
Stack: Next.js (App Router), Tailwind CSS v4, Drizzle ORM, Clerk auth, Zod validation.
## Commands
- Dev server: `npm run dev`
- Production build (also type-checks): `npm run build`
- Lint: `npm run lint`
- Generate migration: `npx drizzle-kit generate`
- Apply migrations: `npx drizzle-kit migrate`
## Project structure
- `app/` holds routes: `page.tsx`, `layout.tsx`, `loading.tsx`, `error.tsx`, `route.ts` for API handlers.
- Shared UI in `components/`, server-only helpers in `lib/` (mark them with `import "server-only"`).
## How to work in this repo
- Read the relevant files before editing. Follow the patterns already in the codebase over these generic rules.
- Make the smallest change that solves the task. Do not refactor or reformat unrelated code.
- Before saying a task is done, run the type-check, lint and tests listed under Commands and fix what you broke.
- If requirements are ambiguous, ask one clear question instead of guessing.
- Never commit secrets, API keys or `.env` files. Use env vars and keep `.env.example` up to date.
- Do not add a new dependency when the standard library or an existing dependency already covers it.
- Ask before adding, removing or upgrading any dependency.
- Ask before changing database schemas, auth, payments or CI configuration.
- Never delete files, drop data or run destructive commands (`rm -rf`, `git push --force`, `DROP TABLE`) without explicit approval.
- Keep each change under ~200 changed lines where possible; split larger work into steps.
## Next.js (App Router)
- Check the Next.js major version in `package.json` before using an API; follow the docs for that version.
- Components are Server Components by default. Add `"use client"` only to the smallest leaf component that needs state, effects, or browser APIs.
- Fetch data in Server Components or Server Actions, not in `useEffect`.
- In Next.js 15+, `params`, `searchParams`, `cookies()` and `headers()` are async: always `await` them.
- Mutations go through Server Actions (`"use server"`) or `route.ts` handlers. Validate every input on the server and re-check auth inside the action.
- After a mutation, call `revalidatePath()` or `revalidateTag()` instead of forcing the whole route dynamic.
- Use `next/image` for images, `next/font` for fonts and `next/link` for internal links.
- Export `metadata` or `generateMetadata` from every page for title, description and Open Graph tags.
- Only variables prefixed `NEXT_PUBLIC_` reach the browser. Never put secrets in them.
- In Next.js 16, `middleware.ts` is renamed `proxy.ts`. Use whichever file the project already has.
## Tailwind CSS v4
- Tailwind v4 is configured in CSS: `@import "tailwindcss";` plus `@theme { ... }` for design tokens. Do not create a `tailwind.config.js` unless the project already has one.
- Use theme tokens (colors, spacing) instead of arbitrary values like `w-[37px]`.
- Build responsive layouts mobile-first with `sm:`, `md:`, `lg:` prefixes.
- Extract repeated class lists into components, not `@apply` chains.
- Support dark mode with the `dark:` variant when the project uses it.
## Drizzle ORM
- Schema lives in TypeScript (`db/schema.ts`). Generate SQL migrations with `drizzle-kit generate` and commit them.
- `drizzle-kit push` is for local prototyping only, never for production databases.
- Infer types with `typeof table.$inferSelect` / `$inferInsert` instead of duplicating interfaces.
- Use the query builder or `sql` template tag; never build SQL with string concatenation.
- Use `db.transaction()` for multi-step writes.
## Clerk auth
- Protect routes with `clerkMiddleware()` and `createRouteMatcher` in the middleware/proxy file.
- On the server use `await auth()` / `await currentUser()` from `@clerk/nextjs/server`, and check `userId` in every Server Action and route handler.
- Use Clerk components (`<SignIn />`, `<UserButton />`) rather than hand-built auth forms.
- `CLERK_SECRET_KEY` is server-only; only the publishable key may be public.
## Zod validation
- Validate all untrusted input (request bodies, form data, env vars, third-party API responses) with a Zod schema at the boundary.
- Derive TypeScript types from schemas with `z.infer<typeof schema>`; do not hand-write duplicate types.
- Use `safeParse` where you need to return validation errors to the user.
## Avoid
- Do not add `"use client"` to layouts or pages just to silence an error; move the interactive part into a child component.
- Do not use the Pages Router (`pages/`) APIs such as `getServerSideProps` in an App Router project.
## Reference docs
- [Next.js docs](https://nextjs.org/docs)
- [Tailwind CSS docs](https://tailwindcss.com/docs)
- [Drizzle docs](https://orm.drizzle.team/docs/overview)
- [Clerk docs](https://clerk.com/docs)
- [Zod docs](https://zod.dev)
Commands your agent should run
| Task | Command |
|---|---|
| Dev server | npm run dev |
| Production build (also type-checks) | npm run build |
| Lint | npm run lint |
| Generate migration | npx drizzle-kit generate |
| Apply migrations | npx drizzle-kit migrate |
What the rules cover
Next.js (App Router)
Next.js App Router with React Server Components and TypeScript. Scoped to app/**/*.tsx, app/**/*.ts, src/**/*.tsx, src/**/*.ts in Cursor, Copilot and Windsurf.
- Check the Next.js major version in
package.jsonbefore using an API; follow the docs for that version. - Components are Server Components by default. Add
"use client"only to the smallest leaf component that needs state, effects, or browser APIs. - Fetch data in Server Components or Server Actions, not in
useEffect. - In Next.js 15+,
params,searchParams,cookies()andheaders()are async: alwaysawaitthem. - Mutations go through Server Actions (
"use server") orroute.tshandlers. Validate every input on the server and re-check auth inside the action. - After a mutation, call
revalidatePath()orrevalidateTag()instead of forcing the whole route dynamic. - Use
next/imagefor images,next/fontfor fonts andnext/linkfor internal links. - Export
metadataorgenerateMetadatafrom every page for title, description and Open Graph tags. - Only variables prefixed
NEXT_PUBLIC_reach the browser. Never put secrets in them. - In Next.js 16,
middleware.tsis renamedproxy.ts. Use whichever file the project already has.
Source docs: Next.js docs
Tailwind CSS v4
Utility-first styling with Tailwind CSS v4. Scoped to **/*.css, **/*.tsx, **/*.vue, **/*.svelte, **/*.astro, **/*.html, **/*.blade.php, **/*.erb in Cursor, Copilot and Windsurf.
- Tailwind v4 is configured in CSS:
@import "tailwindcss";plus@theme { ... }for design tokens. Do not create atailwind.config.jsunless the project already has one. - Use theme tokens (colors, spacing) instead of arbitrary values like
w-[37px]. - Build responsive layouts mobile-first with
sm:,md:,lg:prefixes. - Extract repeated class lists into components, not
@applychains. - Support dark mode with the
dark:variant when the project uses it.
Source docs: Tailwind CSS docs
Drizzle ORM
SQL-like TypeScript ORM with drizzle-kit migrations. Scoped to db/**/*.ts, src/db/**/*.ts, drizzle/** in Cursor, Copilot and Windsurf.
- Schema lives in TypeScript (
db/schema.ts). Generate SQL migrations withdrizzle-kit generateand commit them. drizzle-kit pushis for local prototyping only, never for production databases.- Infer types with
typeof table.$inferSelect/$inferInsertinstead of duplicating interfaces. - Use the query builder or
sqltemplate tag; never build SQL with string concatenation. - Use
db.transaction()for multi-step writes.
Source docs: Drizzle docs
Clerk auth
Authentication and user management with Clerk. Scoped to middleware.ts, proxy.ts, app/**/*.tsx in Cursor, Copilot and Windsurf.
- Protect routes with
clerkMiddleware()andcreateRouteMatcherin the middleware/proxy file. - On the server use
await auth()/await currentUser()from@clerk/nextjs/server, and checkuserIdin every Server Action and route handler. - Use Clerk components (
<SignIn />,<UserButton />) rather than hand-built auth forms. CLERK_SECRET_KEYis server-only; only the publishable key may be public.
Source docs: Clerk docs
Zod validation
Runtime schema validation with Zod. Scoped to **/*.ts, **/*.tsx in Cursor, Copilot and Windsurf.
- Validate all untrusted input (request bodies, form data, env vars, third-party API responses) with a Zod schema at the boundary.
- Derive TypeScript types from schemas with
z.infer<typeof schema>; do not hand-write duplicate types. - Use
safeParsewhere you need to return validation errors to the user.
Source docs: Zod docs
How to install
- Copy
AGENTS.mdto your repo root. That covers Codex, Cursor, GitHub Copilot and most other agents. - Using Claude Code? Add a
CLAUDE.mdwith the single line@AGENTS.md, or use the standalone CLAUDE.md tab above. - Want rules that only load for certain files in Cursor? Add the
.cursor/rules/*.mdcfiles. - Commit the files so your whole team (and every agent) shares them.
FAQ
Where do I put the AGENTS.md for Next.js (App Router) + Tailwind CSS v4 + Drizzle ORM + Clerk auth + Zod validation?
Save it as AGENTS.md in the root of your repository, next to your main config file. Codex, Cursor and GitHub Copilot pick it up automatically. For Claude Code, add a CLAUDE.md containing @AGENTS.md (or use the standalone CLAUDE.md on this page).
What is the most common mistake AI agents make with Next.js (App Router)?
Agents protect pages in middleware but forget to check userId inside Server Actions, which are public endpoints.
Which commands should the agent run to check its work?
For this stack: npm run dev, npm run build, npm run lint, npx drizzle-kit generate. They are listed in the generated files so the agent runs them before finishing a task.
Do these Next.js (App Router) + Tailwind CSS v4 + Drizzle ORM + Clerk auth + Zod validation rules work with Cursor and Claude Code?
Yes. This page includes the same rules as AGENTS.md, CLAUDE.md, Cursor .mdc project rules, a legacy .cursorrules file, GitHub Copilot instructions, Windsurf rules and GEMINI.md.
Can I customise these rules?
Yes. Open this stack in the generator to add or remove libraries, set your project name and package manager, switch beginner explanations on, and download everything as a zip.
Related stacks
Next.js (App Router) + Tailwind CSS v4 + shadcn/ui + Supabase + Zod validation
The default vibe-coding SaaS stack: Next.js App Router, Supabase for auth and Postgres, Tailwind and shadcn/ui for the interface.
Next.js (App Router) + Tailwind CSS v4 + Prisma + Stripe payments + Zod validation
A paid SaaS on Next.js with Prisma and Stripe subscriptions.
Next.js (App Router) + Tailwind CSS v4 + shadcn/ui + Vercel AI SDK + Zod validation
Build an AI chat app or agent UI with Next.js and the Vercel AI SDK.
Next.js (App Router) + Tailwind CSS v4 + Supabase + Stripe payments + Zod validation + Vitest
The full indie-hacker SaaS kit: auth, database, payments and tests.
Next.js (App Router) + Tailwind CSS v4
A plain Next.js + TypeScript + Tailwind v4 starter, the most common front-end setup in 2026.
Next.js (App Router) + Tailwind CSS v4 + Firebase
Next.js with Firebase Auth and Firestore.