Codemods
Source URL: https://nextjs.org/docs/app/guides/upgrading/codemods
Codemods
Section titled “Codemods”Codemods are transformations that run on your codebase programmatically. This allows a large number of changes to be programmatically applied without having to manually go through every file.
Next.js provides Codemod transformations to help upgrade your Next.js codebase when an API is updated or deprecated.
In your terminal, navigate (cd) into your project’s folder, then run:
npx @next/codemod <transform> <path>Replacing <transform> and <path> with appropriate values.
transform- name of transformpath- files or directory to transform--dryDo a dry-run, no code will be edited--printPrints the changed output for comparison
Upgrade
Section titled “Upgrade”Upgrades your Next.js application, automatically running codemods and updating Next.js, React, and React DOM.
npx @next/codemod upgrade [revision]Options
Section titled “Options”revision(optional): Specify the upgrade type (patch,minor,major), an NPM dist tag (e.g.latest,canary,rc), or an exact version (e.g.15.0.0). Defaults tominorfor stable versions.--verbose: Show more detailed output during the upgrade process.
For example:
# Upgrade to the latest patch (e.g. 16.0.7 -> 16.0.8)npx @next/codemod upgrade patch
# Upgrade to the latest minor (e.g. 15.3.7 -> 15.4.8). This is the default.npx @next/codemod upgrade minor
# Upgrade to the latest major (e.g. 15.5.7 -> 16.0.7)npx @next/codemod upgrade major
# Upgrade to a specific versionnpx @next/codemod upgrade 16
# Upgrade to the canary releasenpx @next/codemod upgrade canaryGood to know:
- If the target version is the same as or lower than your current version, the command exits without making changes.
- During the upgrade, you may be prompted to choose which Next.js codemods to apply and run React 19 codemods if upgrading React.
Codemods
Section titled “Codemods”Remove experimental_ppr Route Segment Config from App Router pages and layouts
Section titled “Remove experimental_ppr Route Segment Config from App Router pages and layouts”remove-experimental-ppr
Section titled “remove-experimental-ppr”npx @next/codemod@latest remove-experimental-ppr .This codemod removes the experimental_ppr Route Segment Config from App Router pages and layouts.
export const experimental_ppr = true;Remove unstable_ prefix from stabilized API
Section titled “Remove unstable_ prefix from stabilized API”remove-unstable-prefix
Section titled “remove-unstable-prefix”npx @next/codemod@latest remove-unstable-prefix .This codemod removes the unstable_ prefix from stabilized API.
For example:
import { unstable_cacheTag as cacheTag } from 'next/cache'
cacheTag()Transforms into:
import { cacheTag } from 'next/cache'
cacheTag()Migrate from deprecated middleware convention to proxy
Section titled “Migrate from deprecated middleware convention to proxy”middleware-to-proxy
Section titled “middleware-to-proxy”npx @next/codemod@latest middleware-to-proxy .This codemod migrates projects from using the deprecated middleware convention to using the proxy convention. It:
- Renames
middleware.<extension>toproxy.<extension>(e.g.middleware.tstoproxy.ts) - Renames named export
middlewaretoproxy - Renames Next.js config property
experimental.middlewarePrefetchtoexperimental.proxyPrefetch - Renames Next.js config property
experimental.middlewareClientMaxBodySizetoexperimental.proxyClientMaxBodySize - Renames Next.js config property
experimental.externalMiddlewareRewritesResolvetoexperimental.externalProxyRewritesResolve - Renames Next.js config property
skipMiddlewareUrlNormalizetoskipProxyUrlNormalize
For example:
import { NextResponse } from 'next/server'
export function middleware() { return NextResponse.next()}Transforms into:
import { NextResponse } from 'next/server'
export function proxy() { return NextResponse.next()}Migrate from next lint to ESLint CLI
Section titled “Migrate from next lint to ESLint CLI”next-lint-to-eslint-cli
Section titled “next-lint-to-eslint-cli”npx @next/codemod@canary next-lint-to-eslint-cli .This codemod migrates projects from using next lint to using the ESLint CLI with your local ESLint config. It:
- Creates an
eslint.config.mjsfile with Next.js recommended configurations - Updates
package.jsonscripts to useeslint .instead ofnext lint - Adds necessary ESLint dependencies to
package.json - Preserves existing ESLint configurations when found
For example:
{ "scripts": { "lint": "next lint" }}Becomes:
{ "scripts": { "lint": "eslint ." }}And creates:
import { dirname } from 'path'import { fileURLToPath } from 'url'import { FlatCompat } from '@eslint/eslintrc'
const __filename = fileURLToPath(import.meta.url)const __dirname = dirname(__filename)
const compat = new FlatCompat({ baseDirectory: __dirname,})
const eslintConfig = [ ...compat.extends('next/core-web-vitals', 'next/typescript'), { ignores: [ 'node_modules/**', '.next/**', 'out/**', 'build/**', 'next-env.d.ts', ], },]
export default eslintConfigTransform App Router Route Segment Config runtime value from experimental-edge to edge
Section titled “Transform App Router Route Segment Config runtime value from experimental-edge to edge”app-dir-runtime-config-experimental-edge
Section titled “app-dir-runtime-config-experimental-edge”Note: This codemod is App Router specific.
npx @next/codemod@latest app-dir-runtime-config-experimental-edge .This codemod transforms Route Segment Config runtime value experimental-edge to edge.
For example:
export const runtime = 'experimental-edge'Transforms into:
export const runtime = 'edge'Migrate to async Dynamic APIs
Section titled “Migrate to async Dynamic APIs”APIs that opted into dynamic rendering that previously supported synchronous access are now asynchronous. You can read more about this breaking change in the upgrade guide.
next-async-request-api
Section titled “next-async-request-api”npx @next/codemod@latest next-async-request-api .This codemod will transform dynamic APIs (cookies(), headers() and draftMode() from next/headers) that are now asynchronous to be properly awaited or wrapped with React.use() if applicable.
When an automatic migration isn’t possible, the codemod will either add a typecast (if a TypeScript file) or a comment to inform the user that it needs to be manually reviewed & updated.
For example:
import { cookies, headers } from 'next/headers'const token = cookies().get('token')
function useToken() { const token = cookies().get('token') return token}
export default function Page() { const name = cookies().get('name')}
function getHeader() { return headers().get('x-foo')}Transforms into:
import { use } from 'react'import { cookies, headers, type UnsafeUnwrappedCookies, type UnsafeUnwrappedHeaders,} from 'next/headers'const token = (cookies() as unknown as UnsafeUnwrappedCookies).get('token')
function useToken() { const token = use(cookies()).get('token') return token}
export default async function Page() { const name = (await cookies()).get('name')}
function getHeader() { return (headers() as unknown as UnsafeUnwrappedHeaders).get('x-foo')}When we detect property access on the params or searchParams props in the page / route entries (page.js, layout.js, route.js, or default.js) or the generateMetadata / generateViewport APIs,
it will attempt to transform the callsite from a sync to an async function, and await the property access. If it can’t be made async (such as with a Client Component), it will use React.use to unwrap the promise .
For example:
export default function Page({ params, searchParams,}: { params: { slug: string } searchParams: { [key: string]: string | string[] | undefined }}) { const { value } = searchParams if (value === 'foo') { // ... }}
export function generateMetadata({ params }: { params: { slug: string } }) { const { slug } = params return { title: `My Page - ${slug}`, }}Transforms into:
export default async function Page(props: { params: Promise<{ slug: string }> searchParams: Promise<{ [key: string]: string | string[] | undefined }>}) { const searchParams = await props.searchParams const { value } = searchParams if (value === 'foo') { // ... }}
export async function generateMetadata(props: { params: Promise<{ slug: string }>}) { const params = await props.params const { slug } = params return { title: `My Page - ${slug}`, }}Good to know: When this codemod identifies a spot that might require manual intervention, but we aren’t able to determine the exact fix, it will add a comment or typecast to the code to inform the user that it needs to be manually updated. These comments are prefixed with @next/codemod, and typecasts are prefixed with
UnsafeUnwrapped. Your build will error until these comments are explicitly removed. Read more.
Replace geo and ip properties of NextRequest with @vercel/functions
Section titled “Replace geo and ip properties of NextRequest with @vercel/functions”next-request-geo-ip
Section titled “next-request-geo-ip”npx @next/codemod@latest next-request-geo-ip .This codemod installs @vercel/functions and transforms geo and ip properties of NextRequest with corresponding @vercel/functions features.
For example:
import type { NextRequest } from 'next/server'
export function GET(req: NextRequest) { const { geo, ip } = req}Transforms into:
import type { NextRequest } from 'next/server'import { geolocation, ipAddress } from '@vercel/functions'
export function GET(req: NextRequest) { const geo = geolocation(req) const ip = ipAddress(req)}Migrate ImageResponse imports
Section titled “Migrate ImageResponse imports”next-og-import
Section titled “next-og-import”npx @next/codemod@latest next-og-import .This codemod moves transforms imports from next/server to next/og for usage of Dynamic OG Image Generation.
For example:
import { ImageResponse } from 'next/server'Transforms into:
import { ImageResponse } from 'next/og'Use viewport export
Section titled “Use viewport export”metadata-to-viewport-export
Section titled “metadata-to-viewport-export”npx @next/codemod@latest metadata-to-viewport-export .This codemod migrates certain viewport metadata to viewport export.
For example:
export const metadata = { title: 'My App', themeColor: 'dark', viewport: { width: 1, },}Transforms into:
export const metadata = { title: 'My App',}
export const viewport = { width: 1, themeColor: 'dark',}Use Built-in Font
Section titled “Use Built-in Font”built-in-next-font
Section titled “built-in-next-font”npx @next/codemod@latest built-in-next-font .This codemod uninstalls the @next/font package and transforms @next/font imports into the built-in next/font.
For example:
import { Inter } from '@next/font/google'Transforms into:
import { Inter } from 'next/font/google'Rename Next Image Imports
Section titled “Rename Next Image Imports”next-image-to-legacy-image
Section titled “next-image-to-legacy-image”npx @next/codemod@latest next-image-to-legacy-image .Safely renames next/image imports in existing Next.js 10, 11, or 12 applications to next/legacy/image in Next.js 13. Also renames next/future/image to next/image.
For example:
import Image1 from 'next/image'import Image2 from 'next/future/image'
export default function Home() { return ( <div> <Image1 src="/test.jpg" width="200" height="300" /> <Image2 src="/test.png" width="500" height="400" /> </div> )}Transforms into:
// 'next/image' becomes 'next/legacy/image'import Image1 from 'next/legacy/image'// 'next/future/image' becomes 'next/image'import Image2 from 'next/image'
export default function Home() { return ( <div> <Image1 src="/test.jpg" width="200" height="300" /> <Image2 src="/test.png" width="500" height="400" /> </div> )}Migrate to the New Image Component
Section titled “Migrate to the New Image Component”next-image-experimental
Section titled “next-image-experimental”npx @next/codemod@latest next-image-experimental .Dangerously migrates from next/legacy/image to the new next/image by adding inline styles and removing unused props.
- Removes
layoutprop and addsstyle. - Removes
objectFitprop and addsstyle. - Removes
objectPositionprop and addsstyle. - Removes
lazyBoundaryprop. - Removes
lazyRootprop.
Remove <a> Tags From Link Components
Section titled “Remove <a> Tags From Link Components”new-link
Section titled “new-link”npx @next/codemod@latest new-link .Remove <a> tags inside Link Components.
For example:
<Link href="/about"> <a>About</a></Link>// transforms into<Link href="/about"> About</Link>
<Link href="/about"> <a onClick={() => console.log('clicked')}>About</a></Link>// transforms into<Link href="/about" onClick={() => console.log('clicked')}> About</Link>Migrate from CRA
Section titled “Migrate from CRA”cra-to-next
Section titled “cra-to-next”npx @next/codemod cra-to-nextMigrates a Create React App project to Next.js; creating a Pages Router and necessary config to match behavior. Client-side only rendering is leveraged initially to prevent breaking compatibility due to window usage during SSR and can be enabled seamlessly to allow the gradual adoption of Next.js specific features.
Please share any feedback related to this transform in this discussion.
Add React imports
Section titled “Add React imports”add-missing-react-import
Section titled “add-missing-react-import”npx @next/codemod add-missing-react-importTransforms files that do not import React to include the import in order for the new React JSX transform to work.
For example:
export default class Home extends React.Component { render() { return <div>Hello World</div> }}Transforms into:
import React from 'react'export default class Home extends React.Component { render() { return <div>Hello World</div> }}Transform Anonymous Components into Named Components
Section titled “Transform Anonymous Components into Named Components”name-default-component
Section titled “name-default-component”npx @next/codemod name-default-componentVersions 9 and above.
Transforms anonymous components into named components to make sure they work with Fast Refresh.
For example:
export default function () { return <div>Hello World</div>}Transforms into:
export default function MyComponent() { return <div>Hello World</div>}The component will have a camel-cased name based on the name of the file, and it also works with arrow functions.
Note: Built-in AMP support and this codemod have been removed in Next.js 16.
Transform AMP HOC into page config
Section titled “Transform AMP HOC into page config”withamp-to-config
Section titled “withamp-to-config”npx @next/codemod withamp-to-configTransforms the withAmp HOC into Next.js 9 page configuration.
For example:
// Beforeimport { withAmp } from 'next/amp'
function Home() { return <h1>My AMP Page</h1>}
export default withAmp(Home)// Afterexport default function Home() { return <h1>My AMP Page</h1>}
export const config = { amp: true,}Use withRouter
Section titled “Use withRouter”url-to-withrouter
Section titled “url-to-withrouter”npx @next/codemod url-to-withrouterTransforms the deprecated automatically injected url property on top level pages to using withRouter and the router property it injects. Read more here: https://nextjs.org/docs/messages/url-deprecated
For example:
import React from 'react'export default class extends React.Component { render() { const { pathname } = this.props.url return <div>Current pathname: {pathname}</div> }}import React from 'react'import { withRouter } from 'next/router'export default withRouter( class extends React.Component { render() { const { pathname } = this.props.router return <div>Current pathname: {pathname}</div> } })