AgentStack
SKILL verified MIT Self-run

Next Cache Components Adoption

skill-fellipeutaka-leon-next-cache-components-adoption · by fellipeutaka

>

No reviews yet
0 installs
0 views
view→install

Install

$ agentstack add skill-fellipeutaka-leon-next-cache-components-adoption

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README — it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-fellipeutaka-leon-next-cache-components-adoption)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
8d ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Next Cache Components Adoption? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

next-cache-components-adoption

Enable Cache Components on an app and walk it to a passing build. This skill sequences the work; per-error recipes live in the dev overlay fix cards and the build's terminal output. The migrating to Cache Components guide is the canonical reference for the concepts and per-API recipes this skill applies — consult it whenever the skill steps reference a pattern ("use cache", cacheLife, `` placement, etc.) and you want the full explanation.

requires

  • App Router project. Cache Components is an App Router feature; cacheComponents: true does nothing for pages/ routes. If the project has a pages/ or src/pages/ tree but no app/ or src/app/ tree, stop and tell the user — Pages → App migration is its own project, not part of this skill. A hybrid app (both pages/ and app/) is fine: the flag affects the app/ routes; pages/ routes are unaffected and don't need opt-outs.
  • Next.js 16.3 or later. That release is where the pieces this skill relies on land: top-level cacheComponents, export const instant, the dev-overlay instant-navigation validation warnings, and the cache-components-instant-false codemod. If next --version reports below 16.3, upgrade first:
  • npx @next/codemod@latest upgrade latest to apply the version-to-version codemods.
  • Read the relevant version upgrade guide (e.g. Version 16) for what the codemod doesn't cover.
  • No incompatible config keys. cacheComponents: true errors on any file that still exports dynamic, revalidate, or fetchCache. Translate, don't delete. Each export encodes behavior the route needs to keep doing; migrate each one to its Cache Components equivalent via the migration guide's per-key sections. If a value can't be cleanly translated yet, leave a // TODO: Cache Components adoption — restore revalidate = 3600 comment so the loop picks it up. The cache-components-instant-false codemod does not touch these.
  • experimental.dynamicIO is fatal. It was renamed to top-level cacheComponents and the old key now aborts before any build can run — remove it (or replace with cacheComponents: true) first. experimental.useCache is still accepted as a deprecated alias; redundant once cacheComponents: true is set, so remove it for clarity.

notes

  • No passing baseline before the flag. If the app already uses "use cache", the pre-flag build errors with please enable the feature flag cacheComponents. Enabling the flag is the first thing you do (in Incremental, before the codemod; in Direct, before fixing routes) — not a thing to do after getting a passing build. Note this in your starting summary so it doesn't read as a regression.
  • Offline docs. Guide links have offline copies under node_modules/next/dist/docs/ (bundled since Next.js 16.2), with the directory layout numbered for ordering (e.g. node_modules/next/dist/docs/01-app/02-guides/migrating-to-cache-components.md). If you can't predict the numbered prefix, find node_modules/next/dist/docs -name '.md' resolves it. The /docs/messages/* error pages are not bundled.
  • Older versions without bundled docs. Suggest npx @next/codemod@latest agents-md to the user before starting: it downloads a version-matched copy to .next-docs/ and writes an index into AGENTS.md / CLAUDE.md. It touches files in their repo, so ask first and run it only if they want it.

the shape of the work

There's one loop: walk the route tree top-down, one feature at a time, adopting each route against next dev + a browser. The build is a final check for each feature, not the working surface.

The choice in step 1 is whether to opt every route out of validation first or fix routes as you go. Either way the loop is the same:

  • With a quiet pre-step (Incremental). Run the codemod to opt every page and layout out of validation. Once you've also fixed what the codemod can't (sync-IO calls, leftover revalidate/dynamic/fetchCache exports), the build passes; you ship that as its own PR and then start the loop — removing one opt-out at a time and adopting that route. This splits the work into small, reviewable PRs.
  • Without (Direct). Enable cacheComponents and start the loop on whatever the build flags first. Same loop, but every fix sits on one branch until adoption is complete.

In both, the per-route success bar is the same: dev loop reports no errors AND next build passes. Check in with the user after every feature. Expect to spend most of the time in the loop, not in the pre-step.

background

cacheComponents: true requires every route to be prerenderable. A route that reads request-time data outside ` is "blocking" and fails the build. export const instant = false marks a route as allowed to block, which clears it in both dev and build; on a layout it covers the whole subtree during the build, but client navigations still validate each descendant segment on its own. Reads wrapped in a ["use cache"`](https://nextjs.org/docs/app/api-reference/directives/use-cache) function count as cache boundaries, not blocking reads.

Three classes of blocker come up, usually in this order:

  1. Request-time reads (cookies(), headers(), await params, await searchParams). All four block when awaited at the top of a page or layout. params and searchParams often get missed because they're not framed as "request data" the way cookies and headers are. The fix is to push the read into a `-wrapped child — and for params/searchParams, forward the promise into the child and await it there; don't await` at the page top.
  2. Sync-IO at module/render time (new Date(), Date.now(), Math.random(), crypto.randomUUID()). These fail the build even with instant = false — the opt-out doesn't suppress them. If they're in a shared layout, they block every route under it. The codemod can't fix them; you have to translate each one by hand before the build can pass (see the [incremental pre-step](#incremental)). Grep the whole repo for these calls before running anything else.
  3. "use cache" files that read request data. A file with a top-level "use cache" directive can't export instant; combining the two errors with Only async functions are allowed to be exported in a "use cache" file., which means the directive was wrong for that route. Remove it before running the codemod.

working surfaces

finding blocking routes

Prefer next dev over next build while you work.

  • next dev — the working surface. Visit a route; its blocking errors surface in the dev overlay with full stack traces and fix cards linking the per-error docs. Work one route at a time — errors don't accumulate in one place. The route itself still returns HTTP 200, so read the overlay (or .next-dev.log), not status codes. A cleared overlay is one half of calling a route clean — the other half is browser verification (see [step 2](#step-2-the-inner-loop-remove-opt-outs-one-feature-at-a-time)) and a passing build for that route.
  • next build — detection only. The build is next dev's authoritative check, not its replacement. Use it as the last gate on each feature in the loop (a passing build is part of the per-route success bar) and as the final verification across the whole app. In Incremental, the build also confirms the pre-step (codemod opted every route out, no shared layout still has a sync-IO blocker) before you ship that PR. Don't reach for the build instead of the dev loop while you're working a route — a passing compile doesn't tell you what ended up in the static shell and what streamed. By default the build stops at the first blocking route, so it's also poor for sizing the work. Two flags help when iterating: --debug-build-paths builds only the routes you name (comma-separated glob patterns of file paths relative to the project root, e.g. --debug-build-paths="app/admin/**/page.tsx" — not URL paths; --debug-build-paths="app/(marketing)/about/page.tsx" — not /about; --debug-build-paths="app/admin" matches nothing and silently builds zero routes), and --debug-prerender disables the early exit so the build continues past the first prerender failure, reports every blocking route, and prints a fuller stack trace that names the originating file and line.

Every blocking error has a docs page — open it. Both the dev overlay and the build terminal print a https://nextjs.org/docs/messages/ link with each error. That page is the canonical recipe for the fix; the inline message is a summary. Fetch the link for every distinct error you encounter, even if you think you know the pattern — the recipes evolve, and the same error class can have different correct fixes depending on what the route reads. Don't improvise from the inline message alone. (/docs/messages/* pages aren't bundled offline; if you have no network, fall back to the per-API guides under node_modules/next/dist/docs/ and note the limitation when you report back.)

verifying each fix at runtime

A passing build or a cleared overlay isn't proof the route actually behaves — Cache Components is a runtime concern (a static shell with streamed data). Verify after every fix, not only at the end.

In preference order:

  1. next-dev-loop — strongly preferred. Cross-checks /_next/mcp against the live browser via agent-browser and surfaces both compile and runtime issues in one pass. The diagnostics (React tree, suspense boundaries, console + network) are richer than poking at next dev by hand.

Install it before starting the loop. Don't wait until you hit something next dev alone can't explain. Run:

``bash npx skills add https://github.com/vercel/next.js/tree/canary/skills/next-dev-loop ``

The skill requires agent-browser >= 0.27.0 and walks you through it.

Requires Turbopack. If package.json's dev script passes --webpack, flag it to the user and ask whether there's a reason to stay on webpack. If not, switch to Turbopack (the Next.js 16.3+ default). If they want to keep webpack, skip this install and use the [build-only loop](#the-loop-build-only-fallback) instead.

You don't need permission to install next-dev-loop itself. It's a tool, like installing a dev dependency. If a user is present, briefly tell them you're installing it for verification. In a non-interactive run (CI, dashboard, sandbox), install it without asking — "can't prompt the user" is not a reason to skip. The only legitimate skip is a real technical blocker: no network, no npm, read-only filesystem, a stated no-new-deps policy, or a webpack-only dev script. If you skip, name the specific blocker in your final report.

  1. A browser you can drive yourself. Playwright, agent-browser directly, any browser-automation tool. Use only when next-dev-loop is genuinely blocked. You'll miss the framework-side checks (/_next/mcp), so DOM assertions alone don't catch every regression — be more cautious about what you call "verified."
  1. Build-only. If you can't run a dev server at all, the build is your only signal. ○ (Static) routes with no ` are fully verified by the build (nothing streamed to test). ◐ (Partial Prerender)` routes are only shell-verified — flag them when you report back.
  1. No tooling at all. Ask the user to run the dev server (or build) and report what they see, or commit the milestone you've reached and hand off.

step 1: choose a strategy

Ask the user, in terms of the PRs they want, not the size of the job. Never use the internal labels (Incremental, Direct) when talking to the user — those are your own scaffolding. Ask in terms of PRs and features, e.g.: "Do you want me to first open a PR that turns on Cache Components and opts every route out of validation, then handle the actual route adoptions feature-by-feature in follow-up PRs? Or do everything on one branch?" Even on a tiny app, the incremental path still has value (review-sized PR, revertible, the // TODO: Cache Components adoption markers double as your work queue for next session). Don't pick on their behalf.

If there's no user to ask, default to Incremental and document the choice.

  • Incremental — quiet pre-step + the loop. Run the codemod to opt every page and layout out of validation, get the build passing, stop and check in with the user (see [end of the pre-step](#end-of-the-pre-step-check-in)), then enter [step 2's loop](#step-2-the-inner-loop-remove-opt-outs-one-feature-at-a-time) and ship each feature as a follow-up PR.
  • Direct — skip the pre-step. Enable cacheComponents and go straight to [step 2's loop](#step-2-the-inner-loop-remove-opt-outs-one-feature-at-a-time); the build's blocking routes are the work queue.

incremental

Before invoking the codemod, fix the two classes of blocker it can't.

  1. Sync-IO at module/render time. Grep the whole repo for new Date(), Date.now(), Math.random(), and crypto.randomUUID() (not only app/**/layout.{js,jsx,ts,tsx} — the read might live in any component imported by a layout). Unblock each match with the await connection() + ` fix from its blocking-prerender-* error card: it defers the value to request time, exactly as it behaved before the migration, so it needs no product decision. Add this exact comment on the line above the await connection()`:

``tsx // TODO: Cache Components adoption. Added to unblock the build: remove this connection() to re-trigger the error and review the fix options. ``

It shares the TODO: Cache Components adoption prefix with the comments the codemod writes, so the check-in grep finds both. Removing the await connection() makes the error fire again with its fix cards — the same motion as removing an opt-out in the loop.

  1. Incompatible segment configs. Grep for ^export const (revalidate|dynamic|fetchCache) across app/ and translate per the requires note above. The codemod does not touch them; leaving them in place fails the build after the codemod.

The codemod refuses to run on a dirty working tree. Commit or stash unrelated work first, or pass --force to let its edits land alongside your WIP. Common false positive: if you recently upgraded Next.js, package.json and the lockfile will already be dirty — commit those first.

Use the @canary channel, not @latest. The cache-components-instant-false transform isn't in the stable @next/codemod release; @next/codemod@latest errors with Invalid transform choice.

npx @next/codemod@canary cache-components-instant-false ./app

Inserts export const instant = false (with a // TODO: Cache Components adoption comment) into every app/**/{page,layout,default} file, skipping files that already declare instant and any module marked "use client" or "use server". Then set cacheComponents: true. The TODO comments are the work queue for the loop.

If the codemod isn't available (older @next/codemod, sandboxed environment, offline run), reproduce it by hand: for every app/**/{page,layout,default}.{js,jsx,ts,tsx} that isn't "use client" or "use server" and doesn't already declare instant, insert this after the imports:

// TODO: Cache Components adoption. Refactor this route so this opt-out can be removed.
// See: https://nextjs.org/docs/app/guides/migrating-to-cache-components
export const instant = false

The codemod opts every segment out, not only the root, on purpose. Resolution is top-down, first-explicit-config-wins: the highest instant = false decides the whole subtree. With an opt-out on every segment, remov

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.