Cursor Rules — Next.js App Router (RSC-First)

Project rules for Next.js App Router codebases: server-components-first, server actions with validation, the caching gotchas spelled out, and Tailwind + shadcn conventions.

# Project rules — Next.js (App Router) ## Server-first architecture - Default to React Server Components. Add `'use client'` only for actual interactivity (event handlers, hooks, browser APIs) — and push the boundary down: a client leaf inside a server tree, never a client page with server islands. - Data fetching happens in Server Components or Route Handlers, never in client `useEffect`. Client-side server state, where genuinely needed (polling, optimistic UI), uses TanStack Query. - Mark server-only modules with `import 'server-only'` when they touch secrets or the DB — make the leak a build error, not an incident. ## Server Actions - Every Server Action validates its input with zod at the top — form data is untrusted network input, and "the form only sends valid data" is not a security model. - Every action re-checks authorization inside the action body. Middleware and UI hiding are not authorization. - Return typed results (`{ ok: true, data } | { ok: false, error }`), never throw for expected failures. Call `revalidatePath`/`revalidateTag` explicitly after mutations. ## Caching — assume nothing - Be explicit on every `fetch`: `{ cache: 'no-store' }` or `{ next: { revalidate: N, tags: [...] } }`. Never rely on remembered default behavior — it has changed between Next versions; the explicit option is self-documenting. - Route segments that must be dynamic declare `export const dynamic = 'force-dynamic'` rather than depending on incidental dynamic APIs. - Add `loading.tsx` and `error.tsx` per route segment that fetches; `error.tsx` must offer recovery (`reset()`), not just apologize. ## Components & styling - Tailwind for styling; shadcn/ui for primitives — extend by composition in `components/ui`, never edit generated primitives in place. - Props interfaces named `<Component>Props`, exported. Named exports everywhere; `default` only where the framework requires it (pages, layouts, route handlers). - `next/image` for all raster images with real `width`/`height` or `fill`; `next/link` for all internal navigation. No raw `<img>`, no `<a>` to internal routes. ## Files & boundaries - Feature folders: `app/(group)/feature/` owns its `page.tsx`, `actions.ts`, `components/`. Shared code graduates to `src/lib` or `src/components` only when a second feature imports it. - Environment access only through a zod-validated `src/env.ts`; `NEXT_PUBLIC_` prefix is a deliberate publication decision, reviewed like one. ## When editing - Never add `'use client'` to fix an error you have not understood — it usually masks a server/client boundary mistake. - Match the segment's existing data-fetching pattern before introducing a new one.
Field notes

Comments (0)

LLM Atlas

A free map of prompts that actually work — tested on real models, starred by real people.

© 2026 LLM AtlasPrompts default to CC0 unless stated.