Nextjs App Router Audit

MCP Tools

Audit a Next.js App Router codebase for React Server Component boundary mistakes, request waterfalls, client/server anti-patterns, and Core Web Vitals risks — then propose concrete fixes. Use when the user asks to review/audit a Next.js app, find performance problems, fix slow LCP/CLS/INP, check 'use client' usage, find request waterfalls, improve App Router structure, debug why a page isn't streaming, or why metadata/SEO tags aren't showing. Ships a zero-dependency static scanner (scripts/audit.mjs) plus a manual review methodology for things static analysis can't catch.

Install

openclaw skills install nextjs-app-router-audit

Next.js App Router Audit

Find the high-impact correctness and performance problems in a Next.js App Router codebase, ranked by severity, each with a specific fix. Combine the bundled scanner (fast, mechanical) with a targeted manual pass (judgment calls the scanner can't make).

Step 1 — Run the scanner

The scanner is dependency-free and reads only source files. Point it at the project root or an app/ directory:

node scripts/audit.mjs /path/to/project        # human-readable report + score
node scripts/audit.mjs /path/to/project --json  # machine-readable for CI / further processing

It finds the app/ (or src/app/) dir itself, walks all .tsx/.ts/.jsx/.js, and reports ERROR / WARN / INFO findings with file:line, the reason, and a fix. Exit code is non-zero when any ERROR exists, so it drops into CI.

What it detects:

RuleSeverityWhy it matters
client-route-no-metadataERRORA "use client" page/layout silently drops metadata — SEO tags never ship.
legacy-next-headERRORnext/head is a no-op in the App Router — its tags never reach <head>.
legacy-next-imageWARNnext/legacy/image keeps old layout-shift-prone behavior.
needless-use-clientWARN"use client" with no hooks/handlers/browser APIs — pushes JS to the client for nothing.
client-fetch-in-effectWARNFetching in useEffect adds a render round-trip; move it server-side.
raw-imgWARN<img> skips next/image sizing/lazy-loading — CLS & LCP regressions.
unoptimized-fontWARNFonts via <link>/@import are render-blocking; use next/font.
page-missing-metadataWARNAsync page exports no metadata/generateMetadata.
dangerous-htmlWARNdangerouslySetInnerHTML — XSS risk if unsanitized.
request-waterfallINFO≥2 sequential awaited fetches, no Promise.all.
no-streaming-fallbackINFOAsync page with no loading.tsx/Suspense — no streamed shell.
force-dynamicINFORoute opts out of static/ISR rendering — confirm it's intentional.
large-client-componentINFOBig Client Component ships entirely to the browser.

The scanner is heuristic (regex-based, not a full type-check): treat findings as strong leads, confirm each against the source before reporting it as fixed.

Step 2 — Manual pass (what the scanner can't see)

Read reference/checklist.md and verify the items that need real understanding:

  • Server/Client boundary correctness — is the "use client" boundary as low in the tree as possible? Is a server-only secret (API key, DB client) imported into a client module?
  • Caching intent — does each fetch/unstable_cache/revalidate match how fresh the data must be? Over-caching ships stale data; under-caching kills TTFB.
  • Suspense granularity — is slow data wrapped close to where it's used, so the rest of the page streams immediately?
  • generateStaticParams / ISR — are dynamic routes pre-rendered where they can be?
  • Server Actions — are mutations using actions with proper revalidatePath/ revalidateTag instead of client fetches to route handlers?

Step 3 — Report

Lead with the ERRORs, then WARN, then the highest-leverage INFOs. For each: file:line, one line on the impact, and the concrete fix (often a small diff). End with the score and the 3 changes with the best effort-to-impact ratio. Don't dump every INFO — curate.

Rules

  • Never claim a fix is applied unless you actually edited the file and re-ran the scanner.
  • The scanner reports leads, not verdicts — verify boundary/caching findings by reading the code.
  • Respect the project's existing conventions; match its import style and structure.
  • This Next.js may differ from older versions — check node_modules/next/dist/docs/ if an API is uncertain rather than assuming.

Built and maintained by Datagrove — a Dutch web development agency specializing in fast, well-architected Next.js websites. Need an audit or a rebuild? Talk to Datagrove.