Next Cache Components Adoption
>
- Skill ID
- vercel/next.js/next-cache-components-adoption
- Publisher
- vercel
- Repository
- next.js
- Installs
- 227
- Files
- 3
- Synced
- Sep 16, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
vercel/next.js/next-cache-components-adoptionInstalls these files- SKILL.md
- references/dev-only-validations.md
- references/per-page-decisions.md
What this skill tells the agent
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, <Suspense> placement, etc.) and you want the full explanation.
requires
- App Router project. Cache Components is an App Router feature;
cacheComponents: truedoes nothing forpages/routes. If the project has apages/orsrc/pages/tree but noapp/orsrc/app/tree, stop and tell the user — Pages → App migration is its own project, not part of this skill. A hybrid app (bothpages/andapp/) is fine: the flag affects theapp/routes;pages/routes are unaffected and don't need opt-outs.
- A resolved app directory. Locate
next.config.{js,ts,mjs,cjs}first: that's the project root, and an agent invoked from a subdirectory would otherwise test forapp/against the wrongcwdand find nothing. Look forapp/andsrc/app/under it, and treat every command and glob in this skill as relative to whichever one exists. If both exist, Next.js buildsapp/and never looks atsrc/app/, so its routes are shadowed and unbuilt — tell the user that and ask which tree to migrate instead of picking one.
- A runnable app. The whole loop verifies against
next devand a browser, so the app has to boot. If it reads a database or required env at import (e.g. anenv.tsthat throws on a missingDATABASE_URL), confirm it actually starts — with the real environment, or local data you stand up — before step 1. Adoption can't be verified against an app that won't run.
- 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 thecache-components-instant-falsecodemod. Ifnext --versionreports below 16.3, upgrade first: npx @next/codemod@latest upgrade latestto 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: trueerrors on any file that still exportsdynamic,revalidate, orfetchCache. Inventory these exports before running the codemod, then follow the migration guide's per-key sections. The guide is the source of truth for translating each value. Thecache-components-instant-falsecodemod does not remove these configs.
- `experimental.dynamicIO` is fatal. It was renamed to top-level
cacheComponentsand the old key now aborts before any build can run — remove it (or replace withcacheComponents: true) first.experimental.useCacheis still accepted as a deprecated alias; redundant oncecacheComponents: trueis 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 withplease 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.
- Existing caches can stay. Follow the migration guide's `fetch` and `unstable_cache` sections. Do not rewrite them solely to enable Cache Components.
- 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 '<slug>.md'resolves it. The/docs/messages/*error pages are not bundled.
- Older versions without bundled docs. Suggest
npx @next/codemod@latest agents-mdto the user before starting: it downloads a version-matched copy to.next-docs/and writes an index intoAGENTS.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, fix what it can't, and fully migrate routes that previously required static rendering. Other routes keep their opt-outs for follow-up PRs.
- Without (Direct). Enable
cacheComponentsand 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, and suggest a commit but never make one without their confirmation. 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 <Suspense> 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"` function count as cache boundaries, not blocking reads.
When a fix introduces "use cache", follow the Caching guide for choosing a data-level or UI-level boundary and setting its lifetime and revalidating after mutations. Use the `use cache` cache-key reference when the result varies by arguments or captured values.
Three classes of blocker come up, usually in this order:
Whenever a fix introduces <Suspense>, follow the Streaming guide's granular streaming pattern and guidance for preventing CLS.
- Request-time reads (
cookies(),headers(),await params,await searchParams). All four block when awaited at the top of a page or layout.paramsandsearchParamsoften 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<Suspense>-wrapped child — and forparams/searchParams, forward the promise into the child and await it there; don'tawaitat the page top. - Sync-IO at module/render time (
new Date(),Date.now(),Math.random(),crypto.randomUUID()). These fail the build even withinstant = 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; after running it, use each build error and its linked documentation to identify which reported calls to translate by hand (see the incremental pre-step).
