Skill: next-v16
Next.js 16 App Router (GA October 2025). Prefer the version-matched docs in node_modules/next/dist/docs/ over training data. Codemods: npx @next/codemod@canary upgrade latest, middleware-to-proxy, next-async-request-api.
Scope
- Applies to: Next.js 16 App Router — Turbopack, Cache Components vs previous cache model,
proxy.ts, async request APIs, Server Components, Server Actions, streaming, metadata, client islands - Does NOT cover: Pages Router, generic React 19 (see vercel-react-v1), non-Next server rendering
Assumptions
- Next.js 16.x, React 19.2 App Router, Node.js 20.9+, TypeScript 5.1+
- Two cache models exist. Detect
cacheComponentsinnext.configbefore choosing APIs fetchis not cached by default in either model. Opt in explicitly
Principles
- Read
node_modules/next/dist/docs/for this installed version before generating Next APIs - Cache is opt-in. Declare intent on every server
fetch - Network boundary is
proxy.ts(Node.js). Auth gates, rewrites, redirects, header mutation - Request APIs are async:
await cookies(),await headers(),await draftMode(),await params,await searchParams - Turbopack is the default bundler.
--webpackis an opt-out, not the 16 idiom - Prefer Server Components. Push
'use client'to interactive leaves - When the user asks to audit or modernize Next code, follow
references/_review-algorithm.md
Constraints
MUST
awaitparams,searchParams,cookies(),headers(),draftMode()- Call
revalidateTag(tag, profile)with acacheLifeprofile ('max'|'hours'|'days'| inline{ expire }). One-arg form is deprecated - Use
updateTag(tag)from Server Actions when the user must see the write immediately (read-your-writes). UserevalidateTag(tag, 'max')for stale-while-revalidate - Export
proxyfromproxy.ts(named or default). Runtime isnodejsand cannot be set to Edge - Before adding
'use cache',cacheLife, orcacheTag, confirmcacheComponents: true
SHOULD
- Enable Cache Components only as an explicit migration:
cacheComponents: true, then replace segment configsdynamic/revalidate/fetchCachewith'use cache'+cacheLife. Guide: Migrating to Cache Components - If the app was not adopting
experimental.dynamicIO/experimental.useCache/experimental.ppr, remove those flags. Do not setcacheComponents: trueas a rename — it can fail the build for uncached data outside Suspense - Without Cache Components, cache with
cache: 'force-cache',next: { revalidate, tags }, orunstable_cache. Guide: Caching without Cache Components - Keep a
config.matcheronproxy.tsthat excludes/_next/static,/_next/image, and public assets - Use
next/imageremotePatterns(not deprecatedimages.domains). Usenext/image, notnext/legacy/image - Generate sitemaps/robots from
app/sitemap.tsandapp/robots.ts - Import
cacheLife/cacheTagfromnext/cache(stable). Do not useunstable_cacheLife/unstable_cacheTag - Rename
skipMiddlewareUrlNormalizetoskipProxyUrlNormalize
AVOID
- Generating
'use cache'in an app that has not setcacheComponents: true(directive is a Cache Components feature) - Flipping
cacheComponents: truebecauseexperimental.dynamicIO/experimental.useCache/experimental.pprwere present. Enabling the flag is a programming-model migration middleware.tsfor new code. Keep it only if Edge runtime is still required; it is deprecated- Sync
params/cookies()/headers()(removed, not warned) next lint(removed). Lint with ESLint or Biomeexperimental.ppr,experimental.dynamicIO,experimental.useCache,export const experimental_ppr(removed)experimental.turbopack(moved to top-levelturbopack)experimental.turbo.persistentCaching— that is not the Next 16 API. Filesystem cache isexperimental.turbopackFileSystemCacheForDev/experimental.turbopackFileSystemCacheForBuild(on by default)next dev --turbopack/next build --turbopackas the 16 idiom. Turbopack is already default;--webpackis the opt-out- Custom
webpackin config while running defaultnext build(fails). Migrate to Turbopack or pass--webpack - Treating
'max'onrevalidateTagas “read-your-writes”. That is SWR; useupdateTagin Server Actions - Claiming Server Actions must replace every Route Handler. Route Handlers remain correct for cookies, webhooks, OAuth callbacks, and proxying an external API
Interactions
- React 19 concurrent UI: vercel-react-v1
- Client data after hydration: tanstack-query-v5
- Forms that stay on the Next server: workflow/nextjs-form
Two cache models (do not mix)
| Config | What to generate |
|---|---|
cacheComponents unset / false |
Previous model. fetch uncached unless cache: 'force-cache' or next.revalidate. Segment configs dynamic, revalidate, fetchCache still work. unstable_cache for non-fetch. Do not emit 'use cache' |
cacheComponents: true |
Cache Components. Dynamic by default. Cache with 'use cache' + cacheLife / cacheTag. Segment configs dynamic / revalidate / fetchCache error. PPR is the default behavior. Fetches inside a 'use cache' scope are cached |
'use cache' requires cacheComponents: true (use cache). Enabling the flag is a migration, not an automatic Next 16 default (cacheComponents).
Invalidation (both models, Next 16 signatures):
revalidateTag(tag, 'max')— stale-while-revalidate; works in Server Actions and Route HandlersupdateTag(tag)— expire and read fresh in the same request; Server Actions onlyrefresh()— refresh uncached data only; Server Actions onlyrevalidatePath— unchanged
Next.js 16 idioms (do not generate Next 15)
proxy.ts+export function proxy(Node) — notmiddleware.tsunless Edge is required- Turbopack default —
next dev/next buildwith no--turbopack. Opt out:--webpack await params/await searchParams/await cookies()revalidateTag(tag, profile)— notrevalidateTag(tag)reactCompiler: trueis stable and opt-in (not default)turbopack: { ... }at the Next config root — notexperimental.turbopack- Parallel route slots need
default.js(build fails without it)
How to review or refactor
When the user asks to review, refactor, modernize, or audit Next code, follow references/_review-algorithm.md. Do not improvise.
- Pick Mode A (≤~20 files) or Mode B (whole tree)
- Detect cache model from
next.configbefore Category 2 - Category-major sweep with a scope declaration, per-category progress lines, and a coverage table
- Category 9 last (dedup / consolidate / delete / demote
'use client')
Rule categories
- Build & Bundle — CRITICAL — barrels,
optimizePackageImports,serverExternalPackages, Turbopack,next/dynamic - Caching — CRITICAL — fetch intent, segment config or
'use cache'(model-dependent),revalidateTag+profile,revalidatePath, Reactcache() - Server Components — HIGH — parallel fetch, Suspense, colocation, preload, no client initial fetch
- Routing — HIGH — parallel/intercepting routes, prefetch,
proxy.ts,notFound() - Server Actions — MEDIUM-HIGH — forms,
useFormStatus, action results, optimistic UI, revalidation. Skip when mutations already go to an external API - Streaming — MEDIUM — Suspense,
loading.tsxon routes that await,error.tsx, matching skeletons - Metadata — MEDIUM —
generateMetadata,sitemap.ts,robots.ts,opengraph-image.tsx - Client islands — LOW-MEDIUM —
'use client'leaf, children slot, hydration,next/script - Hygiene — CROSS-CUTTING — dedup fetchers, consolidate routes, dead code, boundary audit, name drift
Full rule list: references/compiled.md. Rule files: references/.