Builds and reviews Next.js App Router code - server/client component boundaries, data fetching, caching and revalidation choices, streaming with Suspense, and Server Action mutations - and delivers routes where every dynamic-vs-cached decision is explicit. Use when someone asks "should this be a client component", "why is my data stale", "where do I put use client", "how do I stream this page", or "how do server actions work". Do NOT use for Vercel-specific runtime and cost tuning of an already-built app - use next-on-vercel-perf instead; for edge middleware and ISR deployment topology - use vercel-edge-and-isr instead; for framework-agnostic Core Web Vitals work - use web-performance instead; for designing an application-wide cache layer beyond the framework - use caching-strategy instead.
Click to play with sound.
---
name: Next.js App Router
description: Builds and reviews Next.js App Router code - server/client component boundaries, data fetching, caching and revalidation choices, streaming with Suspense, and Server Action mutations - and delivers routes where every dynamic-vs-cached decision is explicit. Use when someone asks "should this be a client component", "why is my data stale", "where do I put use client", "how do I stream this page", or "how do server actions work". Do NOT use for Vercel-specific runtime and cost tuning of an already-built app - use next-on-vercel-perf instead; for edge middleware and ISR deployment topology - use vercel-edge-and-isr instead; for framework-agnostic Core Web Vitals work - use web-performance instead; for designing an application-wide cache layer beyond the framework - use caching-strategy instead.
---
# Next.js App Router
Default to Server Components; reach for Client Components only for interactivity, state, or browser APIs. The two costly mistakes this skill prevents are the accidental client tree - one `'use client'` placed high that drags the whole page into the browser bundle - and accidental caching, where `fetch`'s default caching silently serves stale data and the team "fixes" it by sprinkling `force-dynamic` everywhere, losing all caching.
## Operating procedure
### Step 1: gather inputs
Collect before writing a route (label guesses as guesses):
1. Per piece of data on the page: is it per-request/per-user, or shared and cacheable? If cacheable, what staleness is acceptable (seconds, minutes, hours)?
2. Which UI elements genuinely need interactivity, state, effects, or browser APIs.
3. Mutations on the page and what data they invalidate.
4. Auth model: does rendering depend on cookies/headers (forces dynamic rendering)?
### Step 2: draw the client boundary at the leaves
- Mark `'use client'` only at the smallest component that needs it. Everything imported by a client component becomes client code, so a high boundary silently ships the subtree to the browser.
- If a client component needs server-rendered content inside it, pass it as `children` - composition keeps the inner tree on the server.
- Pass data down as props; do not lift server data into client state just to share it.… install to load the full skill