nextjs-app-router-review
Skill7 starsChanged 4 months agoMITView on GitHub
Review Next.js App Router code before you PR for common regressions. Server/client component boundary mistakes, `fetch` cache/revalidate misuse, `params`/`searchParams` async in Next 15+, server-only secrets leaking into client bundles, hydration mismatches, and route handler pitfalls. Triggers include "review this Next.js code", "check my app router page", "why is my page hydrating twice", "server component review".
- Reads credentials
In this repository14 other files it gives its agents.
- ai-tell-cleanupSkill
- branch-guardSkill
- frontend-perf-impact-scanSkill
- jvm-memory-leak-reviewSkill
- kotlin-coroutine-reviewSkill
- nestjs-provider-reviewSkill
- parallel-devSkill
- parallel-dispatchSkill
- parallel-prSkill
- pr-impact-scanSkill
- react-hooks-reviewSkill
- review-loopSkill
- reviewSkill
- spring-kafka-listener-reviewSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 2 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 17
Every file is a server component unless it opens with "use client".
- Very specific: line 24
Use fetch(url, { cache: "no-store" }) for per-request freshness, or { next: { revalidate: N } } for ISR.
- Very specific: line 25
Do not rely on cache: "default".
- Distinctive: line 30
If you support both Next 14 and 15, gate the shape check explicitly.
- Distinctive: line 39
Every middleware invocation is a cold call in production.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
nextjs-app-router-review
Catches Next.js 13+ App Router regressions that are easy to ship and painful to debug in production. Runs before you open a PR.
What to check
1. Server vs client component boundary
- Every file is a server component unless it opens with
"use client". - A
"use client"file must not transitively importserver-onlymodules (db clients, secrets,fs, build-timeprocess.env). If it does, secrets ship to the browser bundle. "use client"propagates. Any component imported by a client component becomes a client component. Verify you did not accidentally client-ify a heavy server tree by importing it from a client parent.- Hooks (
useState,useEffect,useContext, ...) are illegal in server components. Verify bothnext buildand the actual bundle output.
2. Data fetching cache semantics
- Bare
fetch(url)in App Router is cached (SSG-like) by default. Almost never what dashboards want. - Use
fetch(url, { cache: "no-store" })for per-request freshness, or{ next: { revalidate: N } }for ISR. - Do not rely on
cache: "default". The App Router default differs from the browserfetchdefault. - A route becomes dynamic (per-request) as soon as it reads
cookies(),headers(), or unrestrictedsearchParams. Confirm the intended rendering mode in the build output.
3. params and searchParams are async (Next 15+)
- In Next 15,
paramsandsearchParamsare Promises. Await them or wrap inuse(). Not doing so silently returns Promise objects that coerce to[object Object]at runtime. - If you support both Next 14 and 15, gate the shape check explicitly.
4. Route handlers (app/api/*/route.ts)
- Return
ResponseorNextResponse. Returning a plain object gives a 500 with no obvious error. GEThandlers with no cache-control default to static and cache the response. Setexport const dynamic = "force-dynamic"or explicit cache headers.- Handlers do not auto-parse the request body.
await request.json()yourself and error-handle malformed bodies.
5. Middleware
- Runs on Edge runtime. Node built-ins (
fs, mostcrypto,child_process) are unavailable. - Every middleware invocation is a cold call in production. Do not put heavy logic there.
6. Environment variables
process.env.Xin server components is fine. In client components onlyNEXT_PUBLIC_*are available.- A
process.env.SECRET_KEYreferenced inside a"use client"file evaluates toundefinedand often silently branches to unintended code paths.
Common failure patterns to grep for
"use client"at the top of a file that imports fromdb/,auth/, or readsprocess.env.SECRET_*.fetch(...)without an options object in list, dashboard, or admin pages.params.idorsearchParams.qaccessed synchronously in a Next 15 project.export async function GETwithoutdynamic = "force-dynamic"and no explicit cache headers.
When to invoke
Trigger when the user asks for a Next.js code review, mentions App Router pitfalls, or opens a PR touching app/**/page.tsx, app/**/route.ts, middleware.ts, or next.config.*.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

