
Setting up your Next.js project for AI coding agents
If you have spent any time pairing with an AI coding agent on a Next.js project, you have probably watched it confidently write code against an API that no longer exists. It reaches for middleware.ts when your project expects proxy.ts. It imports something from next/router inside a component that lives in the App Router. It writes a getServerSideProps function in a file that is clearly under app/. None of this is because the model is unintelligent — it is because the model's training data has a cutoff date, and Next.js does not stand still. By the time a model finishes training, several minor versions and at least one or two conventions have usually shipped and changed underneath it.
Next.js 16.3 addresses this directly, and not with a blog post or a changelog entry that an agent has to stumble across. It ships the documentation itself, version-matched, inside the package you already install. The idea is refreshingly simple: instead of hoping an agent's training data happens to be current, give it a live, local, always-accurate copy of the docs that travels with your node_modules folder. This article walks through how that system works, how to wire it into a project (new or existing), and the runtime tooling that goes a step further and lets an agent see what is actually happening in your dev server rather than guessing from static code.
Why This Deserves Its Own Setup Step
It is tempting to treat "AI agent configuration" as an optional nicety, something you bolt on after the real work is done. I would push back on that framing. If you are using an agent as a daily collaborator, on Next.js in particular, unpinned assumptions about the framework are one of the most common sources of wasted iteration. An agent that assumes stale APIs will write code that either fails to compile, fails at runtime, or worse, compiles and runs but silently uses a deprecated pattern that gets flagged in a future upgrade.
The App Router itself made this kind of drift more likely than it used to be. The framework has grown faster in the last few years than it did in its first several: Server Components, Server Actions, Cache Components, Partial Prerendering, the Proxy convention that replaced Middleware, and a steady stream of the smaller renames and config option changes that never make headlines but absolutely break code. A model trained even six months ago has a real chance of confidently recommending something that Next.js has since renamed or removed. Treating agent configuration as part of your project setup, the same way you would set up ESLint or TypeScript, closes that gap before it costs you time.
Step 1: Point Agents at the Bundled Docs
The foundation of the whole system is a file called AGENTS.md at your project root. This isn't a Next.js-specific convention on its own — it is an emerging cross-tool standard that most coding agents (Claude Code, Codex, Cursor, GitHub Copilot) already look for automatically at the start of a session. What Next.js adds is the payload: instructions that tell the agent where to find documentation that matches the exact version installed in your project.
That documentation lives at node_modules/next/dist/docs/, and it mirrors the structure of the public docs site:
node_modules/next/dist/docs/
├── 01-app/
│ ├── 01-getting-started/
│ ├── 02-guides/
│ └── 03-api-reference/
├── 02-pages/
├── 03-architecture/
└── index.mdx
This is a genuinely clever piece of design once you think about what it solves. The docs aren't fetched over the network, so there's no dependency on connectivity or an API being reachable mid-session. They aren't a separate download that can drift out of sync, because they ship inside the exact next package version you have installed — upgrade Next.js, and the bundled docs upgrade with it, guidance for newly changed behavior included. An agent reading these docs is, by construction, reading documentation for the version of the framework actually running in your project. That is a much stronger guarantee than "the model was trained recently."
New Projects
If you are starting fresh, you get this for free. create-next-app generates both AGENTS.md and CLAUDE.md automatically as part of scaffolding a new project:
npx create-next-app@canary
pnpm create next-app@canary
yarn create next-app@canary
bun create next-app@canary
If for some reason you don't want these files (maybe your team has its own agent-instructions convention you'd rather not have collide with this one), you can opt out at scaffold time:
npx create-next-app@canary --no-agents-md
Existing Projects
This is the more interesting case, and the one most of you reading this will actually hit. On Next.js 16.3 or later, simply running next dev is enough. If the framework detects that an AI coding agent is present in your environment and no managed block already exists, it will auto-generate AGENTS.md and CLAUDE.md at your project root the first time you run it.
Crucially, this isn't destructive. If you already have an AGENTS.md with your own project-specific instructions, Next.js upserts into it rather than overwriting it, using clearly marked boundary comments:
<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices.
This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean.
<!-- END:nextjs-agent-rules -->
And CLAUDE.md simply imports it:
@AGENTS.md
Anything you write outside those BEGIN/END markers is yours to keep. Next.js will never touch it, even as it continues to update the managed block on future runs. This matters in practice: it means you can add your own conventions (how your team names files, what testing framework you use, links to internal design docs) right alongside the framework's own guidance, and the two coexist without stepping on each other.
One small operational note worth internalizing: because next dev regenerates this block, if you delete it from a diff before committing, running next dev again will simply recreate the uncommitted change. The path of least friction is to just commit the managed block along with your other changes and let it live in version control like any other generated-but-desirable file (think package-lock.json, not .next/).
Opting Out
The Next.js team's own position, backed by their published benchmark results at nextjs.org/evals, is that leaving this auto-generation on measurably improves agent performance. That's a strong enough signal that I'd think twice before disabling it. But if you have a reason to (perhaps a highly custom agent setup that doesn't benefit from it, or a monorepo structure where the generated file causes friction), you can turn it off entirely in your config:
// next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
agentRules: false,
};
export default nextConfig;
Earlier Versions
If you're not yet on 16.3, the bundled docs may or may not be available depending on exactly which version you're on, and the automation definitely isn't:
- On 16.2, the docs are bundled inside
node_modules/next/dist/docs/, but theAGENTS.mdauto-generation doesn't exist yet. You'll need to add the file by hand and simply instruct the agent to read the bundled docs before writing code. - On 16.1 and earlier, the docs aren't bundled at all. Instead, there's a codemod that downloads a version-matched snapshot into a
.next-docs/folder and indexes it for you:
npx @next/codemod@canary agents-md
If your project is on an older version and upgrading isn't immediately practical, this codemod is a reasonable stopgap, even though it lacks the "always current with your installed version" guarantee that the bundled approach gives you for free.
Docs Over the Network
There's a second access path worth knowing about, useful for agents that fetch web pages rather than reading local files (for example, an agent running in a sandboxed environment without access to your node_modules). Every page on nextjs.org/docs is available as plain Markdown by appending .md to the URL, and the same content is served to any client that sends an Accept: text/markdown header. This even covers the per-error documentation pages under /docs/messages, which aren't part of the bundled docs snapshot.
For agents that already know how to consume the llms.txt convention (a lightweight standard for exposing site content to language models), Next.js publishes both an index at /docs/llms.txt and a single-file dump of the entire documentation set at /docs/llms-full.txt. If you're building your own tooling around an agent and want a stable, structured entry point into the docs, these two files are a good place to start rather than scraping the human-facing site.
Step 2: Give Agents Runtime Visibility
Static documentation solves half the problem. The other half is that a coding agent, no matter how well-informed, is fundamentally blind to what's happening in your running application unless something explicitly surfaces that information as text it can read. Next.js closes this gap in a few complementary ways, and this is honestly the part of the system I find most practically useful day to day, agent or no agent.
First, next dev forwards browser console errors and warnings straight to your terminal, controlled by the logging.browserToTerminal config option. This means the terminal output an agent is already reading (because it's the output of the command it just ran) now also contains the client-side failures that used to be invisible unless someone opened DevTools.
Second, next dev writes its process ID, port, and URL to .next/dev/lock. If a second next dev gets started in the same project, instead of silently binding to a different port or erroring cryptically, it prints out the already-running server's URL and the PID you'd need to kill to free it up. This sounds minor, but it's exactly the kind of thing that causes an agent (or a distracted human) to burn several turns debugging "why is my change not showing up" when the real answer is "you're looking at the wrong server instance."
Third, and this is the deeper piece, there's the Next.js MCP server, exposed at /_next/mcp on your running dev server. MCP (Model Context Protocol) is the mechanism by which an agent can query a running system for structured information rather than parsing terminal output. Through this server, an agent can inspect the dev server's routes, its logs, and its compilation state directly. Two tools stand out: get_compilation_issues and compile_route, which let an agent ask "does this specific route actually compile?" without running a full next build just to find out. That's a meaningful time save when you're iterating on a single file and don't want to wait for a full production build cycle just to check for a syntax or type error in one route.
Fourth, there's a complementary tool called agent-browser (maintained by Vercel Labs), which exposes what's happening in the actual browser — the DOM, the console, network requests, Web Vitals — as structured text an agent can read. With React DevTools enabled via agent-browser open --enable react-devtools, it goes further and reports the live component tree, including which Suspense boundaries are still pending. This is the browser's-eye view to complement the MCP server's framework's-eye view.
These two views (framework and browser) come together in a packaged workflow called the next-dev-loop skill, which I'll cover in the next section. Together, they mean an agent working on your project can run something like a react tree command, read the actual state of your rendered UI, and decide what to inspect or fix next — instead of squinting at a description you typed into a chat window trying to explain what's broken.
If you want more background on why this tooling exists in the first place, the Next.js team has published two blog posts specifically about the AI-assisted development story behind these features — worth a read if this space interests you beyond the "how do I configure it" level.
Step 3: Let Errors Drive the Fixes
This is the part of the system that I think is genuinely clever, and it only works if you have Cache Components enabled (the caching model I covered in an earlier article on Caching in the App Router). When a route hits a blocking error during prerendering under Cache Components, Next.js doesn't just print a stack trace. It prints a menu of labeled fixes, each representing a different trade-off, right there in the terminal and in the dev overlay:
Route "/products/[slug]": Next.js encountered uncached data during prerendering.
`fetch(...)` or `connection()` accessed outside of `<Suspense>` prevents the route
from being prerendered, blocking the page load and leading to a slower user experience.
Ways to fix this:
- [stream] Provide a placeholder with `<Suspense fallback={...}>` around the data access
- [cache] Cache the data access with `"use cache"` (does not apply to `connection()`)
- [block] Set `export const instant = false` to allow a blocking route
Learn more: https://nextjs.org/docs/messages/blocking-prerender-dynamic
at ProductPage (app/products/[slug]/page.tsx:52:32)
...
Notice what's happening here: this isn't just an error message, it's a decision tree. The framework knows there are (at minimum) three legitimate ways to resolve this specific class of problem, and it's telling you the shape of each one instead of forcing you or your agent to search the internet to learn what your options even are. In the dev overlay specifically, there's a Copy prompt button that packages whichever fix you pick into a ready-to-paste prompt, one that walks an agent through reading the matching documentation page, applying the canonical pattern for that fix, and then verifying the result at runtime rather than just assuming the fix worked.
This same menu shows up identically in next build output, which matters because it means an agent (or a human) reading CI logs after a failed build sees the exact same structured guidance as someone watching the dev server locally. There's no "you had to be there" gap between local development and CI.
One caveat worth knowing about ahead of time: in development, a stack frame in one of these errors resolves to your actual source file and line. In a production build, server code gets minified, so the stack trace alone might not be enough to locate the problem. For those cases, next build --debug-prerender turns server source maps back on and, importantly, continues past the first failure instead of stopping at it — useful when you have several routes with the same class of problem and want to see all of them in one pass rather than fixing-and-rebuilding one at a time.
The Learn more link in each error isn't a generic search result — it resolves to a specific page under /docs/messages written specifically with agents (and, frankly, humans) in mind. Every one of these pages follows the same shape: the canonical pattern for each fix option, the trade-offs against the alternatives, and the gotchas that are easy to miss on a first attempt. If you're debugging one of these errors and want the full context behind a fix rather than just the one-liner in the terminal, that's the page to open.
Step 4: Hand Multi-Step Workflows to Skills
Here's a distinction that's easy to gloss over but actually matters: everything covered so far (AGENTS.md, the bundled docs, runtime visibility, structured errors) is about giving an agent accurate framework knowledge on demand. Skills are a different thing entirely. They're not knowledge, they're packaged, sequenced workflows for tasks that are genuinely multi-step rather than a single lookup.
The framework's own position, again backed by their benchmark results, is that always-available context (the bundled docs) outperforms on-demand retrieval for foundational framework knowledge. Skills exist for a different category of problem: adopting Cache Components across an entire existing app, or migrating onto Partial Prefetching, aren't things you look up once and apply. They're workflows with checkpoints, verification steps, and decisions that only make sense in the context of your specific codebase.
You can browse the source for these Skills directly in the Next.js GitHub repository, or discover them via skills.sh. They fall into three rough categories:
- Runtime foundations — like
next-dev-loop— give any task, agent-driven or not, a repeatable inspect-edit-verify cycle. - Interactive workflows — like adopting Cache Components — make broader, structural changes with checkpoints where you weigh in.
- Unattended loops work toward a defined, verifiable goal and only stop to ask you something when a genuine decision is required.
next-dev-loop
This is the foundation the other skills build on. It combines the MCP server's framework view with agent-browser's browser view into a single verify-after-every-edit cycle.
npx skills add vercel/next.js --skill next-dev-loop
Then, instead of hoping your agent remembers to check its own work, you make it explicit in your prompt:
After every edit, verify the page still works at runtime using the next-dev-loop Skill.
next-cache-components-adoption
This one is squarely in the "interactive workflow" category. It migrates an app onto Cache Components by:
- Turning the flag on and identifying which routes fail to prerender as a result.
- Fixing them one feature at a time, checking in with you before moving to the next.
- Confirming each fixed feature against both
next devandnext buildbefore considering it done.
npx skills add vercel/next.js --skill next-cache-components-adoption
Adopt Cache Components in this project using the next-cache-components-adoption Skill.
You stay in control of whether the resulting work lands as several small pull requests or stays on a single branch — the skill doesn't make that call for you.
next-cache-components-optimizer
This one leans into the "unattended loop" category and is honestly a neat idea: you tell it what UI you want visible the instant a user clicks a link, and it works backward from that goal.
- It writes a failing
instant()test that encodes the UI you described. - It refactors the route (often by moving a data read below a Suspense boundary) until that test passes.
- It commits the passing test alongside the refactor, so the goal you described becomes a regression test going forward, not just a one-time fix.
It requires a route that already builds successfully under Cache Components, so this one is a follow-up step after adoption, not a replacement for it.
npx skills add vercel/next.js --skill next-cache-components-optimizer
Make the navigation from /settings to /dashboard instant using the next-cache-components-optimizer Skill. The header and the project list should be part of the instant UI.
next-partial-prefetching-adoption
Similar shape to the Cache Components adoption skill, but targeted at moving an app onto Partial Prefetching, where multiple links can share a single App Shell:
- Audits your existing
<Link prefetch={true}>usage with you before changing anything. - Turns the flag on and works through the insights it surfaces.
- Flags routes whose URL-dependent data might be worth prefetching later, without necessarily doing that work automatically.
It assumes Cache Components is already adopted, since Partial Prefetching builds on that model.
npx skills add vercel/next.js --skill next-partial-prefetching-adoption
Adopt Partial Prefetching in this project using the next-partial-prefetching-adoption Skill.
Practical Notes the Docs Don't Spell Out
A few things worth knowing before you set this up, none of which are exactly hidden but also aren't emphasized in the official page:
This is genuinely self-referential. If you're reading this article because an AI agent recommended it, or because you're configuring your own project so an agent like Claude Code stops hallucinating deprecated APIs, that's not a coincidence — it's the entire point of the feature. The system exists specifically because model training cutoffs and framework release cadences are fundamentally mismatched, and bundling the docs is the most direct fix available.
Commit the managed block. I mentioned this above but it's worth repeating because it will trip people up: the <!-- BEGIN:nextjs-agent-rules --> block gets regenerated by next dev if it's missing. If your git hygiene instinct is to keep generated files out of version control, resist that instinct here specifically. This one is meant to be committed, the same way you'd commit a package-lock.json.
Monorepos need a little extra care. The comment inside the generated block itself calls this out: the node_modules/next/dist/docs/ path is resolved relative to the AGENTS.md file's own location, not your repo root. In a monorepo where next is hoisted to a different workspace than the app consuming it, an agent naively looking for node_modules next to the repo root might not find it. Point your agent explicitly at the correct package location if your monorepo structure isn't a simple flat layout.
Runtime visibility beats static analysis for a whole class of bugs. Anyone who has tried to describe a rendering glitch to an AI agent in a chat window knows how lossy that translation is. "The button looks wrong" or "there's a flash of unstyled content" are hard to act on without seeing it. The MCP server and agent-browser combination exists specifically to remove that translation layer, letting the agent look at the actual DOM and console state instead of your description of it.
Skills are opt-in tools, not defaults. It's worth being deliberate about which skills you actually install rather than grabbing all of them reflexively. next-dev-loop is close to universally useful for any agent-driven Next.js work. The Cache Components and Partial Prefetching adoption/optimizer skills are genuinely useful, but only relevant once you've decided to adopt those specific features — installing them on a project that has no intention of using Cache Components just adds noise an agent might reference at the wrong time.
Key Takeaways
| Concern | What Solves It |
|---|---|
| Agent using stale/deprecated APIs | Bundled, version-matched docs at node_modules/next/dist/docs/, referenced via AGENTS.md |
| New project setup | create-next-app generates AGENTS.md/CLAUDE.md automatically |
| Existing project setup | Run next dev on 16.3+; auto-generates and upserts the managed block |
| Opting out entirely | agentRules: false in next.config.ts |
| Pre-16.3 versions | Manual AGENTS.md (16.2) or the agents-md codemod (16.1 and earlier) |
| Agents that fetch over HTTP instead of reading files | Append .md to any docs URL, or use /docs/llms.txt and /docs/llms-full.txt |
| Seeing client-side errors from the terminal | logging.browserToTerminal config, on by default in next dev |
| Framework-level runtime state | Next.js MCP server at /_next/mcp |
| Browser-level runtime state | agent-browser CLI, with React DevTools via --enable react-devtools |
| Structured, actionable build/prerender errors | Cache Components error menu with labeled fix options and a Copy prompt button |
| Multi-step, checkpointed workflows | Skills, such as next-dev-loop, Cache Components adoption/optimizer, Partial Prefetching adoption |
Setting this up takes a few minutes on a project that's already on Next.js 16.3, and effectively nothing on a brand-new one. The payoff isn't dramatic on any single interaction, but it compounds: every session where your agent isn't guessing at an API that changed three versions ago is a session where you spend your time reviewing real code instead of correcting confidently wrong code.


