| name | nextjs |
| description | Next.js 16 App Router performance, caching, server components, server actions, routing, and codebase-hygiene best practices — plus a category-major review/refactor algorithm with codebase-level (remove/dedup/reuse) findings. This skill should be used when writing Next.js 16 App Router code, configuring caching with 'use cache', building Server Components, setting up parallel/intercepting routes, configuring next.config.js OR proxy.ts, OR auditing/refactoring a Next.js codebase (single file or whole repo). This skill does NOT cover generic React 19 patterns (use react skill) or non-Next.js server rendering. |
Next.js 16 App Router Best Practices
Comprehensive Next.js 16 App Router guide for AI agents. Contains 45 rules across 9 categories, prioritized by impact from critical (build optimization, caching strategy) through to cross-cutting codebase hygiene (dedup, dead routes, boundary coherence). Reflects Next.js 16 changes: 'use cache' directive replacing implicit caching, revalidateTag(tag, cacheLife) requirement, proxy.ts replacing middleware.ts, Turbopack persistent caching, App Router conventions.
Rule files describe pattern shapes (not API names) and open with a "Shapes to recognize" section listing 2–4 syntactic disguises the same break can wear. Selected high-value rules (those whose disguises are most common in practice — 'use cache', parallel-fetching, dynamic-imports, server-action-forms, client-boundary, server-vs-client-fetching) include an extra concrete "In disguise" incorrect/correct example pair to teach pattern detection beyond the grep-friendly cases.
When to Apply
- Writing new Next.js 16 App Router code
- Auditing or modernizing a Next.js codebase — single file, PR, or whole repo (see
references/_review-algorithm.md)
- Migrating from Next.js 15 to 16 (implicit caching →
'use cache', middleware.ts → proxy.ts, revalidateTag single-arg → with cacheLife)
- Configuring caching strategies with
'use cache', unstable_cache, revalidateTag, revalidatePath
- Implementing Server Components and parallel/colocated data fetching
- Setting up parallel routes, intercepting routes, prefetching,
proxy.ts
- Creating Server Actions for form handling and mutations
- Tuning
'use client' boundaries to minimize client bundle
- Finding codebase-level issues that single-file rules can't see: duplicated server fetchers, near-duplicate routes/layouts, dead routes,
'use client' propagation across the route tree, prop-shape drift (see Category 9)
How to Review or Refactor a Codebase
When the user asks to review, refactor, modernize, or audit Next.js code — single file or whole repo — follow references/_review-algorithm.md. Do not improvise.
Four non-negotiables from that doc:
- Two modes — never refuse a whole-repo audit. Pick Mode A (scoped, ≤~20 files) or Mode B (whole-tree: inventory pass + targeted sweeps + full Category 9).
- Judgment over grep. Each rule names a pattern shape, not a syntactic marker. Read each rule's Shapes to recognize section before sweeping — grep finds the easy violations and misses the high-value ones (a layout marked
'use client' for one button; TanStack Query fetching initial page data; a route handler doing the work of a Server Action; a hand-rolled cache layer mimicking 'use cache'; sequential fetches hidden across parent/child Server Components).
- Category-major, not file-major — with forcing functions. Sweep one category at a time across all in-scope files in priority order (CRITICAL → … → CROSS-CUTTING). The algorithm requires a scope declaration, per-category progress lines, and a final coverage table (category × file/bucket, cells ∈
{clean, N findings, n/a}). A missing category in the output is immediately visible.
- Codebase-level findings come from Category 9. Single-file rules can't tell you "these two routes should be one" or "this server action is dead." Category 9 (Codebase Hygiene) sweeps the full inventory at the end and produces remove / dedup / reuse / consolidate findings.
Single-file ad-hoc questions ("is this caching strategy right?") can go straight to the relevant rule. The algorithm exists for the multi-file and whole-repo cases.
Rule Categories
| # | Category | Impact | Rules | Key Topics |
|---|
| 1 | Build & Bundle Optimization | CRITICAL | 5 | Turbopack, optimizePackageImports, dynamic imports, barrel files, serverExternalPackages |
| 2 | Caching Strategy | CRITICAL | 6 | 'use cache', revalidateTag+cacheLife, fetch options, segment config |
| 3 | Server Components & Data Fetching | HIGH | 6 | Parallel fetching, streaming, colocation, preload, no-client-fetch, error handling |
| 4 | Routing & Navigation | HIGH | 5 | Parallel routes, intercepting routes, prefetching, proxy.ts, notFound() |
| 5 | Server Actions & Mutations | MEDIUM-HIGH | 5 | Server actions, useFormStatus, action-result errors, useOptimistic, revalidation |
| 6 | Streaming & Loading States | MEDIUM | 5 | Suspense placement, loading.tsx, error.tsx, skeleton matching, nested Suspense |
| 7 | Metadata & SEO | MEDIUM | 4 | generateMetadata, sitemap.ts, robots.ts, opengraph-image.tsx |
| 8 | Client Components | LOW-MEDIUM | 4 | 'use client' boundary, children pattern, hydration mismatch, next/script |
| 9 | Codebase Hygiene | LOW-MEDIUM | 5 | Dedup server fetchers, route consolidation, dead routes/actions, 'use client' propagation, prop drift |
Quick Reference
Critical patterns — get these right first:
- Add
'use cache' to Server Components/functions whose results should be cached (Next.js 16 dropped implicit fetch caching)
- Call
revalidateTag(tag, cacheLife) with a profile — never the one-arg API
- Configure
optimizePackageImports for icon/utility libraries with flat-export surfaces
- Don't disable Turbopack persistent caching
- Wrap
<form action={serverAction}> instead of POST-to-/api/...
Next.js 16 idioms (do NOT generate Next.js 15 patterns):
proxy.ts (Node runtime) — not middleware.ts (Edge)
- Explicit
'use cache' — not implicit fetch caching
revalidateTag(tag, cacheLife) — not single-arg revalidateTag(tag)
- Server Action +
useActionState — not client fetch + useState
app/sitemap.ts — not hand-maintained public/sitemap.xml
Common single-file mistakes — avoid these anti-patterns:
- Sequential
await for independent data (use Promise.all or preload)
useEffect + fetch in a Client Component for initial page data
'use client' at the layout level for one interactive button
- Missing
revalidatePath/revalidateTag after a mutating Server Action
- Skeletons that don't match content dimensions (CLS hit)
Codebase-level patterns — surface these in Category 9 sweeps:
- 2+ Server Components hitting the same upstream with drifting cache policies — extract to a shared cached fetcher
- 2+ near-duplicate routes/layouts that should be one with a variant or dynamic segment — consolidate
- Routes / route handlers / Server Actions with no inbound traffic for 90+ days — delete (after analytics check)
'use client' propagating up the route tree because of one interactive leaf — demote layouts/parents to Server Components, leave a client island
- Same concept under different route-param/search-param/prop names — converge on a canonical name (watch out for SEO redirects)
Table of Contents
- Build & Bundle Optimization — CRITICAL
- Caching Strategy — CRITICAL
- Server Components & Data Fetching — HIGH
- Routing & Navigation — HIGH
- Server Actions & Mutations — MEDIUM-HIGH
- Streaming & Loading States — MEDIUM
- Metadata & SEO — MEDIUM
- Client Components — LOW-MEDIUM
- Codebase Hygiene — CROSS-CUTTING (multi-file findings; required for whole-repo audits)
References
- Next.js Documentation
- Next.js 16 Release Notes
- React Documentation
- Vercel Engineering Blog
Related Skills
- For React 19 fundamentals (concurrent rendering, hooks, components), see
react skill
- For client-side form handling, see
react-hook-form skill
- For client data caching with TanStack Query, see
tanstack-query skill
Full Compiled Document
For the complete guide with all rules expanded: AGENTS.md