### Why?
Async Request API codemods can leave temporary casts that still require
application-specific repairs. Those locations need explicit markers,
while optional feature adoption needs to be distinguishable from
required version migrations.
### How?
Add `@next-codemod-error` comments to temporary `UnsafeUnwrapped*`
casts, with instructions for completing the repair. Preserve documented
ignores and avoid duplicating casts or markers when the transform runs
again. Mark generated Cache Components opt-outs with
`@next-codemod-ignore`, a removal condition and a link to the adoption
guide.
Add `upgrade --skip-adoption` to skip the Cache Components `instant =
false` transform and partial-prefetch adoption cleanup. Required
migrations and normal dependency and bundler selection keep their
existing behavior. Both adoption transforms can still be run explicitly.
## What
Follow-up to #95365. Documents adopting Partial Prefetching end to end:
- Restructures the [Adopting Partial Prefetching
guide](https://github.com/vercel/next.js/blob/canary/docs/01-app/02-guides/adopting-partial-prefetching.mdx)
around the two paths: enable `partialPrefetching` and audit every `<Link
prefetch={true}>` against a per-case decision table, or adopt
incrementally per route with the
[`instant-link-prefetch-partial`](https://nextjs.org/docs/messages/instant-link-prefetch-partial)
insight as the worklist. Adds `Auditing routes for URL data` and
`Prefetching URL data` sections.
- Adds the `remove-partial-prefetch` codemod, which strips the redundant
per-route `prefetch = 'partial'` exports once the flag is on while
preserving comments and other `prefetch` values.
- Adds the `next-partial-prefetching-adoption` skill that sequences the
guide for agents: audit, enable + codemod, URL-data sweep, verify,
optional runtime prefetching.
- Aligns the `instant-link-prefetch-partial` error page, `<Link>`
reference, glossary, and Interactive apps guide with the same prefetch
model.
## Why
With the flag on, `<Link prefetch={true}>` no longer delivers dynamic
content, and shell validation flags `params`/`searchParams` reads
outside `<Suspense>`. Adopters need one guide that sequences the audit,
the flag, and both insights, and an agent skill that follows it.
Stacked on #95365 (base: `codex/instant-shell-link-data`) since it links
to the `instant-shell-url-data` error page that PR introduces. GitHub
will retarget to `canary` when that merges.
<!-- NEXT_JS_LLM_PR -->
### Why?
Turning on `cacheComponents` makes every blocking route a build error at
once. On a large app that's a wall of failures with no clear order to
fix them in, which is a rough first experience.
### What?
An opt-in adoption path so enabling Cache Components doesn't have to be
all-or-nothing:
- **`cache-components-instant-false` codemod** (`@next/codemod`) —
blanket-inserts `export const instant = false` (with a `// TODO: Cache
Components adoption` comment) into every `app/**/{page,layout}` file, so
the build goes green immediately. Idempotent: skips files that already
export `instant` (including aliased `export { x as instant }`). Skips
Client Components (`"use client"`) and route handlers.
- **`next-cache-components-adoption` skill** (`skills/`) — sequences the
full migration in five steps across four milestones: green build
(codemod or direct), remove the opt-outs top-down one group at a time,
make navigations instant via the dev-overlay Insights, then adopt
Partial Prefetching. It defers individual fixes to the dev overlay fix
cards, stack traces, and the `/docs/messages/blocking-prerender-*`
pages, and points at the migration / instant-navigation / Partial
Prefetching guides rather than re-teaching them. Verifies each change at
runtime via `next-dev-loop` (with a manual dev-overlay fallback). The
`next-cache-components-optimizer` skill is referenced only as optional
shell-growing polish after adoption is complete.
### How?
- Transform registered in `TRANSFORMER_INQUIRER_CHOICES` at `version:
'16.3.0'`.
- 8 fixtures cover insert-into-page / -layout, JSDoc placement, and
no-op on existing / aliased / multi-declarator / local-binding `instant`
and on `"use client"` pages. `pnpm jest cache-components-instant-false`
passes.
- Docs: a `cache-components-instant-false` entry in the codemods
reference, and a pointer to the skill + codemod from the migration
guide.
ESLint `FlatCompat` can be used in two ways:
```js
compat.extends('next/core-web-vitals', 'next/typescript')
```
```js
compat.config({
extends: ['next/core-web-vitals', 'next/typescript'],
})
```
Although using `.extends()` is recommended for migration, and the ESLint
migration tool also uses that, it is possible to use `.config()`, so
handle them as well for the migration.
Confirmed on local apps as well.
Stacked on https://github.com/vercel/next.js/pull/84874
### Why?
As `eslint-config-next` supports Flat config since PR
https://github.com/vercel/next.js/pull/84874, Release
[v16.0.0-canary.6](https://github.com/vercel/next.js/releases/tag/v16.0.0-canary.6),
update codemod to use Flat config. Since `eslint-config-next` version
and this codemod's version will match, no need to gate the version, as
by the time this change is released, the same `eslint-config-next`
version will support Flat config.
### How?
Updated to handle the three cases:
- Legacy config
- Flat config with FlatCompat (Which we used to recommend for v15)
- Flat config with no FlatCompat (Which means the app does not use
`eslint-config-next`)
For the Legacy config, ESLint provides a [Migration
tool](https://eslint.org/docs/latest/use/configure/migration-guide), so
use that to convert to Flat config. It will include FlatCompat, so the
rest of the process is the same as Flat config with FlatCompat.
For the Flat config with FlatCompat, the codemod will remove FlatCompat
and map the `eslint-config-next` imports directly to the export.
For the Flat config with no FlatCompat, the codemod will import
`eslint-config-next` and map the imports directly to the export.
Tested on
[shadcn/ui](https://github.com/shadcn-ui/ui/blob/cb769b7059b50b5dca033a6eb57bb8ecde69fc87/.eslintrc.json)
and other large legacy ESLint configs.
Stacked to https://github.com/vercel/next.js/pull/84119
This PR adds a codemod for renaming `middleware` to `proxy`. Below are
the behaviors:
- Rename `middleware.*`, `src/middleware.*` to `proxy.*`, `src/proxy.*`
- Rename function/variable exports from `middleware` to `proxy`. Default
exports are skipped.
The `legacyBehavior` prop of the `Link` component has been deprecated
since #77473. For Next.js 16, we're finally removing support for it.
Consequently, we're also removing support for the `passHref` prop, which
was only useful in conjunction with the `legacyBehavior` prop.
A [codemod is
available](https://nextjs.org/docs/app/guides/upgrading/codemods#new-link)
to help you automatically upgrade your codebase.
reverts #77473
---------
Co-authored-by: Sebastian Sebbie Silbermann <sebastian.silbermann@vercel.com>
## Add codemod to migrate from `next lint` to ESLint CLI
This PR introduces a new codemod `next-lint-to-eslint-cli` that helps
users migrate away from the deprecated `next lint` command to using
ESLint directly, in preparation for Next.js 16 where `next lint` will be
removed.
### What it does
The codemod automates the migration process by:
1. **Updating package.json scripts** - Replaces all `next lint` commands
with `eslint` equivalents
- Maps Next.js-specific flags (`--strict` → `--max-warnings 0`,
`--dir`/`--file` → paths)
- Preserves other ESLint-compatible flags
- Handles complex scripts with pipes, redirects, and multiple commands
2. **Managing ESLint configuration**
- Creates a new flat config (`eslint.config.mjs`) if none exists
- Updates existing flat configs to include Next.js rules
- Provides guidance for legacy configs that need manual migration
3. **Installing dependencies automatically**
- Adds required packages: `eslint`, `eslint-config-next`,
`@eslint/eslintrc`
- Detects and uses the project's package manager (npm/yarn/pnpm/bun)
- Falls back to manual instructions if installation fails
### Usage
```bash
npx @next/codemod@latest next-lint-to-eslint-cli .
```
### Example transformations
```json
// Before
{
"scripts": {
"lint": "next lint",
"lint:fix": "next lint --fix",
"lint:strict": "next lint --strict --dir src"
}
}
// After
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint --fix .",
"lint:strict": "eslint --max-warnings 0 src"
}
}
```
### Why this change?
- `next lint` is being deprecated and will be removed in Next.js 16
- ESLint v9+ flat config is becoming the standard
- Direct ESLint usage provides more flexibility and better ecosystem
compatibility
- Reduces Next.js maintenance burden of wrapping ESLint functionality
The codemod ensures a smooth transition path for existing Next.js
projects while following ESLint best practices.
This adds a new transform to `@next/codemod` that updates
`next.config.{js,ts}` that updates the deprecated `experimental.turbo`
property to the new top-level `turbopack` property.
Details:
- Only operates on files called next.config.js or next.config.ts, in the
case the codemod tool is run on a large codebase.
- Updates _any_ object literal with a `experimental.turbo` property to
use `turbopack`. Since this transform is constrained to Next.js configs,
there shouldn’t be many false positives.
- Much of this change was written by Copilot. I simplified it, and
refactored it to make it more readable and safe.
Test Plan:
- `pnpm run build && pnpm test -- -t
next-experimental-turbo-to-turbopack` in the codemod directory
- Tested on several publicly available next configs that used the
deprecated property
### Why?
We had breaking change in App Router at
https://github.com/vercel/next.js/pull/70480 where it strictly checks
`runtime` route segment config. If it is set to `experimental-edge`,
will throw. Therefore we support a codemod to replace it to `edge`.
> [!NOTE]
> This codemod requires to install the `@vercel/functions` package.
### Why?
Codemod support for breaking change at
https://github.com/vercel/next.js/pull/68379. It removed the `ip`, and
`geo` properties from the `NextRequest` type. The `NextRequest` type was
mostly used in the `middleware` and `route`.
### How?
The codemod replaces the `ip`, and `geo` properties from the
`NextRequest` with corresponding `@vercel/functions` features.
#### Accessing NextRequest Value
When a file uses `NextRequest`, we look if there's an access to the type
with `geo` or `ip`. This targets destructuring and direct access.
```ts
export function GET (req: NextRequest) {
const { geo, ip: ipAlias, pathname } = req // destructuring
// direct access
req.geo
req.ip
}
```
Declares a variable based on the identifier within the object. If it was
aliased, we use the aliased name.
```ts
import { geolocation, ipAddress } from '@vercel/functions'
export function GET (req: NextRequest) {
const { pathname } = req // destructuring
const geo = geolocation(req)
const ipAlias = ipAddress(req)
// direct access
geolocation(req)
ipAddress(req)
}
```
#### Accessing NextRequest Types
When the file has accessed the `geo | ip` type from `NextRequest`, we
replace with the corresponding types.
```ts
import type { NextRequest } from 'next/server'
export function GET (req: NextRequest) {
const ip = '...' as NextRequest['ip']
const geo = { ... } as NextRequest['geo']
}
```
Since the type for `ip` is `string | undefined`, we explicitly replace
it. For `geo`, we replace with the `Geo` type.
```ts
import type { NextRequest } from 'next/server'
import type { Geo } from '@vercel/functions'
export function GET (req: NextRequest) {
const ip = '...' as string | undefined
const geo = { ... } as Geo
}
```
### Ref
Behavior FYI:
https://github.com/vercel/next.js/pull/70064#discussion_r1768718840,
https://github.com/vercel/next.js/pull/70064#discussion_r1768722282
Closes NDX-291
---------
Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
Co-authored-by: Donny/강동윤 <kdy1997.dev@gmail.com>
Co-authored-by: Jiachi Liu <inbox@huozhi.im>
### What
Provide a codemod to transform the promise of the access to named export
properties in dynamic import `next/dynamic`, this codemod transform all
the `next/dynamic` imports to ensure returning an object value with
`default` property, aligning with what `React.lazy` is returning
### Why
Follow up for #66990
It's not allowed to do dynamic import and access it's named export while
using `next/dynamic` in server component, and the dynamic import module
is from a client component. It's like accessing the nested client side
property of a module
This PR adds the codemods transforming certain fields from `metadata`
export to `viewport` export, will still preserve rest metadata export
properties. We don't cover `generateMetadata` to `generateViewport` as
there might be more complex logic inside the function which is hard to
apply the codemods rules.
TLDR: Codemods for #57302
<!--
Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:
-->
Fix for https://github.com/vercel/next.js/issues/46459
In order to test this, I've updated the `next-image-to-legacy-image`
tests to use fixtures that are written in TypeScript. I've disabled
type-checking and linting on those test fixtures, because they are
pretty noisy.
## Bug
- [x] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see
[`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)
## Feature
- [ ] Implements an existing feature request or RFC. Make sure the
feature request has been accepted for implementation before opening a
PR.
- [ ] Related issues linked using `fixes #number`
- [ ]
[e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see
[`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)
## Documentation / Examples
- [ ] Make sure the linting passes by running `pnpm build && pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing
doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
This PR fixes `next/image` codemods and makes sure that the tests are properly testing the codemods using the `tsx` parser. This is accomplished by make sure each codemod declares the `tsx` parser instead of the CLI.
Related to: https://twitter.com/styfle/status/1625992439428263937
Fixes issue #41925 by skipping duplicate props. I've tested the changes
locally - the duplicate prop is being skipped successfully. The
new-link.test.js suite is also passing.
<!--
Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change that you're making:
-->
## Bug
- [x] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `contributing.md`
## Feature
- [ ] Implements an existing feature request or RFC. Make sure the
feature request has been accepted for implementation before opening a
PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see `contributing.md`
## Documentation / Examples
- [ ] Make sure the linting passes by running `pnpm build && pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing
doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
Co-authored-by: Ishaq Ibrahim <ishaq.ibrahim@convertdigital.com.au>
This adds two codemods for `next/image`.
The first codemod a safe solution to upgrade from 12 to 13 by swapping
to `next/legacy/image`.
The second codemod is an experimental solution that attempts to automate
the [migration
guide](https://nextjs.org/docs/api-reference/next/future/image#migration).
Fixes https://github.com/vercel/next.js/discussions/32233⚠️ If you're looking at this PR please read the complete description including the part about incremental adoption.
## TLDR:
Official support for `<Link href="/about">About</Link>` / `<Link href="/about"><CustomComponent /></Link>` / `<Link href="/about"><strong>About</strong></Link>` where `<Link>` always renders `<a>` without edge cases where it doesn’t render `<a>`. You'll no longer have to put an empty `<a>` in `<Link>` with this enabled.
## Full context
### Changes to `<Link>`
- Added an `legacyBehavior` prop that defaults to `true` to preserve the defaults we have today, this will allow to run a codemod on existing codebases to move them to the version where `legacyBehavior` becomes `false` by default
- When using the new behavior `<Link>` always renders an `<a>` instead of having `React.cloneElement` and passing props onto a child element
- When using the new behavior props that can be passed to `<a>` can be passed to `<Link>`. Previously you could do something like `<Link href="/somewhere"><a target="_blank">Download</a></Link>` but with `<Link>` rendering `<a>` it now allows these props to be set on link. E.g. `<Link href="/somewhere" target="_blank"></Link>` / `<Link href="/somewhere" className="link"></Link>`
### Incremental Adoption / Codemod
The main reason we haven't made these changes before is that it breaks pretty much all Next.js apps, which is why I've been hesitant to make this change in the past. I've spent a bunch of time figuring out what the right approach is to rolling this out and ended up with an approach that requires existing apps to run a codemod that automatically opts their `<Link>` usage into the old behavior in order to keep the app functioning.
This codemod will auto-fix the usage where possible. For example:
- When you have `<Link href="/about"><a>About</a></Link>` it'll auto-fix to `<Link href="/about">About</Link>`
- When you have `<Link href="/about"><a onClick={() => console.log('clicked')}>About</a></Link>` it'll auto-fix to `<Link href="/about" onClick={() => console.log('clicked')}>About</Link>`
- For cases where auto-fixing can't be applied the `legacyBehavior` prop is added. When you have `<Link href="/about"><Component /></Link>` it'll transform to `<Link href="/about" legacyBehavior><Component /></Link>` so that your app keeps functioning using the old behavior for that particular link. It's then up to the dev to move that case out of the `legacyBehavior` prop.
**This default will be changed in Next.js 13, it does not affect existing apps in Next.js 12 unless opted in via `experimental.newLinkBehavior` and running the codemod.**
Some code samples of what changed:
```jsx
const CustomComponent = () => <strong>Hello</strong>
// Legacy behavior: `<a>` has to be nested otherwise it's excluded
// Renders: <a href="/about">About</a>. `<a>` has to be nested.
<Link href="/about">
<a>About</a>
</Link>
// Renders: <strong onClick={nextLinkClickHandler}>Hello</strong>. No `<a>` is included.
<Link href="/about">
<strong>Hello</strong>
</Link>
// Renders: <strong onClick={nextLinkClickHandler}>Hello</strong>. No `<a>` is included.
<Link href="/about">
<CustomComponent />
</Link>
// --------------------------------------------------
// New behavior: `<Link>` always renders `<a>`
// Renders: <a href="/about">About</a>. `<a>` no longer has to be nested.
<Link href="/about">
About
</Link>
// Renders: <a href="/about"><strong>Hello</strong></a>. `<a>` is included.
<Link href="/about">
<strong>Hello</strong>
</Link>
// Renders: <a href="/about"><strong>Hello</strong></a>. `<a>` is included.
<Link href="/about">
<CustomComponent />
</Link>
```
---
## Feature
- [x] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [x] Related issues linked using `fixes #number`
- [x] Integration tests added
- [x] Errors have helpful link attached, see `contributing.md`
Co-authored-by: JJ Kasper <22380829+ijjk@users.noreply.github.com>
Previously our automatic React injection approach injected `import React from 'react'` automatically whenever JSX was detected. The new official JSX transform solves this by enforcing importing `React` when it is used.
This codemod automatically converted files that are using a "global React variable" to use `import React from 'react'`