Skip to content

Next.js App Router prompt

Rules that make your coding agent write Next.js 16 the way it works today: Server Components first, Cache Components, async params, proxy.ts and Server Functions.

What it makes your agent good at

Agents trained on Next.js 13 to 15 still write middleware.ts, read params synchronously, add use client to whole pages and fetch their own API routes. This prompt points them at the docs that ship with your Next.js version and gives them the current model: Server Components by default, explicit caching, Server Functions for writes.

  1. Server Components by defaultuse client only on the interactive leaf; data read in Server Components, never through the app's own API routes.
  2. Cache Components, explicitlyuse cache with cacheLife and cacheTag for shared reads, Suspense around every request-time read, so pages prerender a static shell.
  3. Async request APIsparams, searchParams, cookies() and headers() awaited, typed with the generated PageProps and LayoutProps helpers.
  4. Writes that refresh the right dataValidated, authorized Server Functions that return errors as values, then updateTag, revalidateTag with a profile, or refresh.
  5. Next.js 16, not 13proxy.ts instead of middleware.ts, catchError and retry for errors, no Pages Router APIs or removed config.
  6. Checks its own workThe docs in node_modules/next/dist/docs and the dev server's MCP endpoint before guessing an API.

The Next.js App Router rules

90 lines, current to Next.js 16.4 and React 19.3. Last reviewed October 23, 2026. Plain Markdown, no front matter: each agent's is below.

Download

nextjs-app-router.md

# Next.js App Router

You are working in a Next.js 16 App Router project with React 19 and TypeScript. Write code for the version in `package.json`, not the one in your training data: much of what you remember from Next.js 13 to 15 has changed.

## Before you write code

- Read the version-matched docs in `node_modules/next/dist/docs/` (Next.js 16.2 and later ship them) before using an API you are not sure of. `01-app/03-api-reference/` holds the exact signatures; heed deprecation notes.
- Check `next.config.ts` for `cacheComponents`, `partialPrefetching` and `typedRoutes`: they change how pages render, cache and type their links.
- With `next dev` running, its MCP endpoint (`/_next/mcp`) reports compilation issues and errors per route. Prefer it to a full `next build` while you iterate.

## Project shape

- Routes live in `app/` (or `src/app/`). Only `page.tsx` and `route.ts` are public; colocate private files in `_folders`, group without changing the URL with `(groups)`.
- One `proxy.ts` at the root replaces `middleware.ts` (renamed in Next.js 16). Export `function proxy(request: NextRequest)` and a `config.matcher`. It runs on Node.js; use it for redirects, rewrites and headers, never for slow data fetching or as your only auth check.
- Server-only modules (database, secrets, the session) start with `import "server-only"`. Only that data access layer reads `process.env` secrets.
- Type page and layout props with the generated global helpers: `PageProps<"/blog/[slug]">`, `LayoutProps<"/dashboard">`, `RouteContext<"/api/items/[id]">`. They come from `next typegen`, `next dev` or `next build`.

## Server and Client Components

- Components are Server Components by default. Add `"use client"` only to the leaf that needs state, effects, event handlers or browser APIs, never to a page or layout just to make an error go away.
- Pass Server Components into Client Components as `children` or props instead of importing them there.
- Props crossing to the client must be serializable: no functions (except Server Functions), class instances or Dates you rely on as objects.
- Context providers are Client Components rendered as deep as possible, wrapping `{children}`.
- Read data in Server Components: `await` a query or `fetch` directly in the component. No `useEffect` fetching, no API route the same app then calls from its own server.
- Wrap shared reads in React's `cache()` so a layout and a page asking for the same user hit the database once.

## Request APIs are async

`params`, `searchParams`, `cookies()`, `headers()` and `draftMode()` return promises. Always `await` them in Server Components (or read them with `use()` in a Client Component).

```tsx
export default async function Page(props: PageProps<"/blog/[slug]">) {
  const { slug } = await props.params;
  const post = await getPost(slug);
  if (!post) notFound();
  return <Article post={post} />;
}
```

## Caching with Cache Components

When `cacheComponents: true` is set (the default for new apps), nothing is cached unless you say so, and every page is prerendered into a static shell:

- Mark cached work with the `"use cache"` directive at the top of an async function, component or page, and pair it with `cacheLife("hours" | "days" | "max" | …)` from `next/cache`. Arguments and captured values become the cache key.
- Tag what a mutation will invalidate: ``cacheTag("posts", `post-${id}`)``.
- Uncached reads (`fetch` without cache, the database, `cookies()`, `headers()`, `searchParams`) must sit inside a `<Suspense>` boundary with a real fallback; otherwise the dev overlay reports a blocking route. The fallback ships in the static shell and the content streams in.
- Read request data outside the cached scope and pass the value in as an argument. Use `"use cache: private"` only for results that must read cookies or headers themselves, and `"use cache: remote"` for a durable shared cache.
- Before reading `new Date()`, `Math.random()` or `crypto.randomUUID()` in a Server Component, either cache it or `await io()` (from `next/cache`) inside a Suspense boundary.
- Do not use `export const dynamic`, `revalidate` or `fetchCache` segment options, `unstable_cache` or `unstable_noStore` in a Cache Components app: they belong to the previous model. If `cacheComponents` is off, follow the previous model's docs instead and do not mix the two.

## Mutations: Server Functions

- Write mutations as Server Functions in a `"use server"` file (`app/actions.ts`) or inline in a Server Component. They are public HTTP endpoints: validate every input with a schema (Zod), check the session and authorize the user inside each one.
- Call them from a `<form action={…}>` first, so forms work before JavaScript loads; use `useActionState` for pending state and returned errors, `useFormStatus` in a submit button, `useOptimistic` for instant feedback.
- Return expected errors as values (`{ ok: false, errors }`); throw only for bugs.
- After a write: `updateTag(tag)` when the user must see their own change at once (Server Functions only), `revalidateTag(tag, "max")` for stale-while-revalidate (the profile argument is required since Next.js 16), `revalidatePath` for a whole route, `refresh()` to refresh the client router without invalidating data, `redirect()` last, outside `try`/`catch`.
- Route Handlers (`app/api/**/route.ts`) are for webhooks, streaming responses and clients outside your app, not for your own pages' data.

## Routing and navigation

- Use `<Link>` for internal navigation and `next/navigation` (`useRouter`, `usePathname`, `useSearchParams`) in Client Components. `useSearchParams` needs a `<Suspense>` boundary above it.
- Each segment can have `loading.tsx`, `error.tsx` (a Client Component receiving `error` and `retry`) and `not-found.tsx`. Call `notFound()` and `redirect()` from Server Components and Server Functions (`forbidden()` and `unauthorized()` need `experimental.authInterrupts`).
- For an error boundary around one component rather than a route, use `catchError` from `next/error` instead of writing a class boundary.
- Parallel route slots need a `default.tsx`.
- Prerender known dynamic segments with `generateStaticParams`.

## Metadata and assets

- Export `metadata` or `generateMetadata` from layouts and pages; set `metadataBase` once in the root layout. Use `opengraph-image.tsx`, `icon.tsx`, `sitemap.ts` and `robots.ts` file conventions instead of hand-written tags.
- Use `next/image` with `width` and `height` (or `fill` and `sizes`) and remote patterns in `images.remotePatterns` (`images.domains` is deprecated); use `next/font` for fonts, applied once on `<html>`.
- Load third-party scripts with `next/script`, never a raw `<script>` in a component.

## Config and tooling

- Turbopack is the default for `next dev` and `next build`; its options live under `turbopack` in `next.config.ts`. Do not add a webpack config unless the project already has one.
- `next lint` was removed: run ESLint or Biome directly as the project's scripts do.
- Environment variables exposed to the browser start with `NEXT_PUBLIC_` and are inlined at build time; everything else stays on the server.

## Do not

- Do not write `getServerSideProps`, `getStaticProps`, `next/router` or `pages/` APIs in an App Router project.
- Do not read `params` or `searchParams` synchronously, or call `revalidateTag` with one argument.
- Do not fetch your own Route Handlers from Server Components, or pass secrets and whole database rows to Client Components.
- Do not add `"use client"` to a layout, put `async` on a Client Component, or call `redirect()` inside `try`.

## Before you finish

- Run the type checker (`tsc --noEmit` or the project's typecheck script) and the linter, and fix what they report.
- Check the dev overlay or `/_next/mcp` for blocking-route and hydration issues on every page you touched.
- Say which routes are prerendered, cached or streamed when you change caching, so the reviewer knows what to test.

7,970 characters, 1,191 words. Under Windsurf's 12,000-character limit for a rule, as every prompt here is.

Use it in your agent

The same rules, where your agent reads them. Each file has the front matter its agent needs, set to apply on every request.

Claude Code

A rule it loads every session

  1. Save it as .claude/rules/nextjs-app-router.md in your project, front matter included, or run the install command.
  2. Claude Code loads every file in .claude/rules with your CLAUDE.md when a session starts.
  3. Prefer one file? Paste it into CLAUDE.md under its own heading instead.

.claude/rules/nextjs-app-router.md

# Next.js App RouterYou are working in a Next.js 16 App Router project with React 19 and TypeScript. Write code for the version in `package.json`, not the one in your training data: much of what you remember from Next.js 13 to 15 has changed.## Before you write code- Read the version-matched docs in `node_modules/next/dist/docs/` (Next.js 16.2 and later ship them) before using an API you are not sure of. `01-app/03-api-reference/` holds the exact signatures; heed deprecation notes.- Check `next.config.ts` for `cacheComponents`, `partialPrefetching` and `typedRoutes`: they change how pages render, cache and type their links.- With `next dev` running, its MCP endpoint (`/_next/mcp`) reports compilation issues and errors per route. Prefer it to a full `next build` while you iterate.## Project shape…

Or let the shadcn CLI write this file: sign in (free) for your command.

Cursor

A project rule with front matter

  1. Save it as .cursor/rules/nextjs-app-router.mdc, front matter included, or run the install command.
  2. alwaysApply: true adds it to every Agent request in this project.
  3. Check it under Cursor Settings, Rules, then commit the folder for your team.

.cursor/rules/nextjs-app-router.mdc

---description: "Next.js 16 App Router conventions: Server and Client Components, caching, Server Functions, routing files and proxy.ts."alwaysApply: true---# Next.js App RouterYou are working in a Next.js 16 App Router project with React 19 and TypeScript. Write code for the version in `package.json`, not the one in your training data: much of what you remember from Next.js 13 to 15 has changed.## Before you write code- Read the version-matched docs in `node_modules/next/dist/docs/` (Next.js 16.2 and later ship them) before using an API you are not sure of. `01-app/03-api-reference/` holds the exact signatures; heed deprecation notes.- Check `next.config.ts` for `cacheComponents`, `partialPrefetching` and `typedRoutes`: they change how pages render, cache and type their links.- With `next dev` running, its MCP endpoint (`/_next/mcp`) reports compilation issues and errors per route. Prefer it to a full `next build` while you iterate.## Project shape…

Or let the shadcn CLI write this file: sign in (free) for your command.

Windsurf

A workspace rule for Cascade

  1. Save it as .windsurf/rules/nextjs-app-router.md, or run the install command.
  2. trigger: always_on applies it to every Cascade request in this workspace.
  3. Windsurf reads up to 12,000 characters per rule; this one is 7,970.

.windsurf/rules/nextjs-app-router.md

---trigger: always_on---# Next.js App RouterYou are working in a Next.js 16 App Router project with React 19 and TypeScript. Write code for the version in `package.json`, not the one in your training data: much of what you remember from Next.js 13 to 15 has changed.## Before you write code- Read the version-matched docs in `node_modules/next/dist/docs/` (Next.js 16.2 and later ship them) before using an API you are not sure of. `01-app/03-api-reference/` holds the exact signatures; heed deprecation notes.- Check `next.config.ts` for `cacheComponents`, `partialPrefetching` and `typedRoutes`: they change how pages render, cache and type their links.- With `next dev` running, its MCP endpoint (`/_next/mcp`) reports compilation issues and errors per route. Prefer it to a full `next build` while you iterate.## Project shape…

Or let the shadcn CLI write this file: sign in (free) for your command.

GitHub Copilot

Instructions for the repository

  1. Save it as .github/instructions/nextjs-app-router.instructions.md, or run the install command.
  2. applyTo: "**" applies it to every request in this repository.
  3. Or paste it into .github/copilot-instructions.md, which Copilot reads for every request.

.github/instructions/nextjs-app-router.instructions.md

---description: "Next.js 16 App Router conventions: Server and Client Components, caching, Server Functions, routing files and proxy.ts."applyTo: "**"---# Next.js App RouterYou are working in a Next.js 16 App Router project with React 19 and TypeScript. Write code for the version in `package.json`, not the one in your training data: much of what you remember from Next.js 13 to 15 has changed.## Before you write code- Read the version-matched docs in `node_modules/next/dist/docs/` (Next.js 16.2 and later ship them) before using an API you are not sure of. `01-app/03-api-reference/` holds the exact signatures; heed deprecation notes.- Check `next.config.ts` for `cacheComponents`, `partialPrefetching` and `typedRoutes`: they change how pages render, cache and type their links.- With `next dev` running, its MCP endpoint (`/_next/mcp`) reports compilation issues and errors per route. Prefer it to a full `next build` while you iterate.## Project shape…

Or let the shadcn CLI write this file: sign in (free) for your command.

Codex & AGENTS.md

The file most agents read

  1. Paste it into AGENTS.md at your project's root, under its own heading.
  2. Codex reads AGENTS.md before it starts work, and so do Cursor, Zed, Jules, Amp and Copilot's coding agent.
  3. A folder can have its own AGENTS.md: the one closest to the file being edited wins.

AGENTS.md

## Next.js App RouterYou are working in a Next.js 16 App Router project with React 19 and TypeScript. Write code for the version in `package.json`, not the one in your training data: much of what you remember from Next.js 13 to 15 has changed.### Before you write code- Read the version-matched docs in `node_modules/next/dist/docs/` (Next.js 16.2 and later ship them) before using an API you are not sure of. `01-app/03-api-reference/` holds the exact signatures; heed deprecation notes.- Check `next.config.ts` for `cacheComponents`, `partialPrefetching` and `typedRoutes`: they change how pages render, cache and type their links.- With `next dev` running, its MCP endpoint (`/_next/mcp`) reports compilation issues and errors per route. Prefer it to a full `next build` while you iterate.### Project shape…

AGENTS.md is shared with your own instructions, so paste the rules in: the copy sets their headings a level down.

Rules teach it. The MCP equips it. With Pro, your agent installs every component, block and icon it needs, from a prompt.

Get Pro

Pricing

Give your agent the parts, with Pro

The prompts are free. Every Pro plan adds the MCP server, so your agent installs the components, blocks and icons it writes code around.

4.9/5 out of 5 · 150+ reviewsfrom 150+ founders and developers.

  • Secure checkout via Stripe
  • Code lives in your repo
  • Keep what you've shipped if you cancel
  • License terms

Next.js App Router prompt FAQ

What the Next.js App Router prompt covers and how to use it in your agent.

Does the Next.js App Router prompt cover Cache Components?

Yes. With cacheComponents on, nothing is cached until you mark it, so the prompt has your agent add the use cache directive with a cacheLife profile and cacheTag to the reads that can be shared, and wrap per-request reads in Suspense. Without Cache Components it tells the agent to follow the previous model instead of mixing the two.

When does the agent use updateTag instead of revalidateTag?

updateTag expires a tag and refreshes it in the same request, so a user sees their own change at once; it only runs in Server Functions. revalidateTag marks a tag stale and serves the old result while it refreshes, and since Next.js 16 it takes a cacheLife profile as its second argument. The prompt has the agent pick by whether the writer must see the change.

Why does the prompt insist on Suspense around cookies and headers?

Because an uncached read or a cookie read outside a boundary blocks the static shell, and Next.js reports it as a blocking route. The prompt has the agent wrap each request-time read in Suspense with a real fallback, so the shell prerenders and the rest streams in.

4.9 out of 5 from 150+ developers

Rules teach it. The MCP equips it.

Every component, block and icon, installed by your AI agent on your stack. The prompts stay free.

Get Pro
  • Cancel anytime
  • Keep what you've shipped