ref


The goal of this doc is



<aside> đź’ˇ For this doc, leave your feedback as a comment on this public document.

To report an issue with codemods, use the reporting feature inside VS Code extension, or just open an issue in the Codemod Registry.

</aside>

Migration Steps

Explaination of Step IDs V = Versioning N = Navigation B = Bootstrapping C = Server & Client Components A = API Routes

Step ID Step Name Codemod name Codemod deep-link Auto Cov. Description of Changes
V1 Bump React and React DOM to the newest version - - Now: 0%
N/A
V2 Bump Next.js version to v13.4 in the project - - Now: 0%
Find all package.json files and bump the next property to ^13.4.0. After that, run your package manager to update your respective node_modules files
N1 Replace router.query usages with useSearchParams Replace Next Router vscode://intuita.intuita-vscode-extension/showCodemod?chd=-wqkAQr7ILgYeTRozWTEgiUvmSY Now: 80%

| The router prototype coming from the return value of useRouter from next/navigation does no longer have the query attribute. You can replace this functionality by using the return value of useSearchParams from next/navigation . We will call this value searchParams from this moment on.

The searchParams might be nullable if it is used within the pages directory. Otherwise, they will be a read-only URLSearchParams map, not a plain old JavaScript object like query.

You can use the nullability of the searchParams to check if the routing is already available to use in your component.

The searchParams might contain multiple results under one key. To get values for key a, write either searchParams?.getAll('a') or searchParams?.get('a'). It is safer to use getAll.

You cannot delete values from searchParams. The similar behavior would be to use the push or replace functionality of Next.js’ router. | | N2 | Replace router.asPath with usePathname | Replace Next Router | https://codemod.notion.site/8ad7726316924beea415884a9d679ddc | Now: 80% | The router prototype coming from the return value of useRouter from next/navigation does not contain the asPath attribute. You can use the return value of the usePathname hook from next/navigation. We will call this return value the pathname from this moment on.

The pathname might be nullable if it is used within the pages directory. Otherwise, they will be a string.

You can use the nullability of the pathname to check if the routing is already available to use in your component. | | N3 | Replace router.pathname with usePathname | Replace Next Router | vscode://intuita.intuita-vscode-extension/showCodemod?chd=-wqkAQr7ILgYeTRozWTEgiUvmSY | Now: 80% | The router prototype coming from the return value of useRouter from next/navigation does not contain the pathname attribute. You can use the return value of the usePathname hook from next/navigation. | | N4 | Remove the router.isFallback usages | Replace Next Router | vscode://intuita.intuita-vscode-extension/showCodemod?chd=-wqkAQr7ILgYeTRozWTEgiUvmSY | Now: 80% | The router prototype coming from the return value of useRouter from next/navigation does not contain the isFallback attribute. The fallback functionality is no longer supported.

Since you might have boolean expressions that depend on router.isFallback, you might want to remove the branches that depend on router.isFallback being true. | | N5 | Replace router.isReady with true | Replace Next Router | vscode://intuita.intuita-vscode-extension/showCodemod?chd=-wqkAQr7ILgYeTRozWTEgiUvmSY | Now: 80% | The router prototype coming from the return value of useRouter from next/navigation does not contain the isFallback attribute.

You can either replace router.isReady with true (and subsequently remove branches executed when router.isReady was true) or use a nullability check over useSearchParams, usePathname or useParams return values. | | N6 | Reduce number of router.push and router.replace arguments to 1 | Replace Next Router | vscode://intuita.intuita-vscode-extension/showCodemod?chd=-wqkAQr7ILgYeTRozWTEgiUvmSY | Now: 80% | The router prototype coming from the return value of useRouter from next/navigation contains a simplifying version of the push method.

The first and only argument in the new API is the string href. You can get it by transforming the first argument into string (which might require conversion from an URLObject).

The second parameter of the old API is not supported. If you use it, you need to readjust the href parameter in the new API accordingly.

The third parameter of the old API is not supported. Automated scrolling should be achieved by writing the scrolling code yourself. Shallow routing is not supported. Locale needs to be handled by your custom code. | | N7 | Remove router.basePath usages and implement this feature in a different way | - | - | Now: 0% | The router prototype coming from the return value of useRouter from next/navigation does not contain the basePath attribute.

You can replace usages of router.basePath with a constant string you likely have put into the basePath attribute of the default-exported object in next.config.js | | N8 | Remove router.locale, router.locales , router.defaultLocale, and router.domainLocales and implement internationalization in a different way | - | - | Now: 0% | The router prototype coming from the return value of useRouter from next/navigation does not contain the locale, locales, defaultLocale and domainLocales attributes.

Locales are no longer supported directly in the App Router of Next.js. Pick your own solution or follow the guide here: https://nextjs.org/docs/pages/building-your-application/routing/internationalization | | N9 | Remove router.events | - | - | Now: 0% | The router prototype coming from the return value of useRouter from next/navigation does not contain the events attribute.

The router events are not directly supported. You can react on pathname and searchParams changes as outlined here: https://nextjs.org/docs/app/api-reference/functions/use-router#router-events | | N10 | Replace useRouter from next/router to useRouter from next/navigation | Replace Next Router | vscode://intuita.intuita-vscode-extension/showCodemod?chd=-wqkAQr7ILgYeTRozWTEgiUvmSY | Now: 100% | Once all to-be-removed properties of router have been handled, we can switch to use the router object as returned from useRouter from next/navigation | | B1 | Create the root layout | App Directory Boilerplate | vscode://intuita.intuita-vscode-extension/showCodemod?chd=QKEdp-pofR9UnglrKAGDm1Oj6W0 | Now: 50% | Create a component that renders the rudimentary top-level HTML in app/layout.tsx (html and body tags are mandatory).

https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration#step-2-creating-a-root-layout | | B1.1 | Update dynamic imports | App Directory Boilerplate | | Now: 0% Soon: 0% | Module resolution changes can affect dynamic imports in API Routes. https://www.notion.so/intuita/Module-Resolution-in-API-Routes-9325e55ab3314e9c8d1801b8f37ac6e1 | | B1.2 | Update _app providers | App Directory Boilerplate | | Now: 0% Soon: 0% | Some libraries previously used in _app (e.g next-i18next) dont support next 13 app router. Such libraries should be replaced or forked and fixed. | | B2 | Add global styles to the root layout file | App Directory Boilerplate | vscode://intuita.intuita-vscode-extension/showCodemod?chd=QKEdp-pofR9UnglrKAGDm1Oj6W0 | Now: 100% | Put global styles imports in app/layout.tsx | | B3 | Migrate the styles | Move CSS in JS Styles | vscode://intuita.intuita-vscode-extension/showCodemod?chd=fPpa1xqB9D0AN4VazhrRkrWri9g | Now: ~20% Soon: TBD | Some CSS libraries might not be supported by Next.js. You need to check your CSS architecture and pick a proper solution. see the https://nextjs.org/docs/app/building-your-application/styling/css-in-js | | B4 | Add metadata to the root layout file | Replace Next Head | vscode://intuita.intuita-vscode-extension/showCodemod?chd=HCouE4WzwvH-jcfOJ3xYLz4YaTA | Now: 80% Soon: 100% | Next/Head meta tags should be moved to the metadata object or generateMetadata function. https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration#step-3-migrating-nexthead | | B5 | Create the root app/page.tsx | App Directory Boilerplate | vscode://intuita.intuita-vscode-extension/showCodemod?chd=QKEdp-pofR9UnglrKAGDm1Oj6W0 | Now: 80% | Migrate the server components of pages/_app.tsx and pages/_document.tsx to app/page.tsx The client components should be either part of the root “client component” file or the “root layout”.

Breaking changes:

https://nextjs.org/docs/pages/api-reference/next-config-js/runtime-configuration | | B11 | Migrate away from req and res objects in the getInitialProps function. | - | - | Now: 0% Soon: 25% | Instead of accessing req and res objects, you can use cookies and headers hooks in the server components.

https://nextjs.org/docs/app/api-reference/functions/cookies https://nextjs.org/docs/app/api-reference/functions/headers | | B12 | Create the root error page (app/error.tsx) | App Directory Boilerplate | vscode://intuita.intuita-vscode-extension/showCodemod?chd=nARTEpqaNCsnGw3tnJN6B45fMB0 | Now: 25% | This step is optional.

If you have pages/_error.tsx implement, you likely need to copy its contents to app/error.tsx.

Follow the guide here: https://nextjs.org/docs/app/building-your-application/routing/error-handling | | B13 | Create the app/not-found.tsx page | App Directory Boilerplate | vscode://intuita.intuita-vscode-extension/showCodemod?chd=nARTEpqaNCsnGw3tnJN6B45fMB0 | Now: 25% | This step is optional.

If you have pages/404.tsx implement, you likely need to copy its contents to app/not-found.tsx.

Follow the guide here: https://nextjs.org/docs/app/api-reference/file-conventions/not-found | | C1 | Create a page.tsx file (the main host for the server components) for each route. | App Directory Boilerplate | vscode://intuita.intuita-vscode-extension/showCodemod?chd=nARTEpqaNCsnGw3tnJN6B45fMB0 | Now: 80%

| https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration#step-4-migrating-pages For each page, we should create a page.tsx in an appropriate directory in the app root directory. This file is a place for the server component logic. Separate the server-component and client-component logic.

Each page.tsx should contain a default-exported async function that is a React-Server component. | | C2 | Migrate the functionality in every occurrence of getServerSideProps to everypage.tsx | Remove Get Static Props | vscode://intuita.intuita-vscode-extension/showCodemod?chd=gqDiMZhaiz_RSzyfHeUueiYcGFI | Now: 80% | In every page within the pages directory, read what getServerSideProps do and reimplement it by getting the same information directly in the main page.tsx component. The concept of getServerSideProps is not applicable in the App router.

https://nextjs.org/docs/pages/api-reference/functions/get-server-side-props | | C3 | Migrate the functionality in every occurrence of getStaticProps to everypage.tsx | Remove Get Static Props | vscode://intuita.intuita-vscode-extension/showCodemod?chd=gqDiMZhaiz_RSzyfHeUueiYcGFI | 100% | In every page within the pages directory, read what getStaticProps do and reimplement it by getting the same information directly in the main page.tsx component. The concept of getStaticProps is not applicable in the App router.

https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration#static-site-generation-getstaticprops | | C4 | Migrate the functionality in every occurrence of getInitialProps to everypage.tsx | - | - | Now: 0% Soon: 80% | In every page within the pages directory, read what getInitialProps do (providing the starting props for the server component) and reimplement it in every page.tsx default React-server component. The concept of getInitialProps is not directly translatable in the App router.

https://nextjs.org/docs/pages/api-reference/functions/get-initial-props | | C5 | Reimplement getStaticPaths as generateStaticParams in every page.tsx | Remove Get Static Props | vscode://intuita.intuita-vscode-extension/showCodemod?chd=gqDiMZhaiz_RSzyfHeUueiYcGFI | Now: 80% Soon: 90% | Generate static routes at build-time.

https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration#dynamic-paths-getstaticpaths https://nextjs.org/docs/pages/api-reference/functions/get-static-props | | C6 | Implement metadata object or generateMetadata function in every page.tsx , if the page or its child components define meta tags using Next/Head. | Replace Next Head | vscode://intuita.intuita-vscode-extension/showCodemod?chd=HCouE4WzwvH-jcfOJ3xYLz4YaTA | Now: 100% | Generate metadata to be consumed by the SEO by declaring an async function called generateMetadata on the root-level of every page.tsx, if applicable.

You can also implement an exported metadata object if you don’t need an async function. https://nextjs.org/docs/app/api-reference/functions/generate-metadata | | C7 | Create a components.tsx file or similar (the main host for the client-rendered page’s component) for every route. | App Directory Boilerplate (work in progress) | vscode://intuita.intuita-vscode-extension/showCodemod?chd=nARTEpqaNCsnGw3tnJN6B45fMB0 | Now: 0% | This file will host a client-side-rendered component. The file should be tagged with 'use client'; directive at the beginning of it. The file’s components should be imported in the page.tsx file in the same directory. | | C8 | Create a layout.tsx page for every route, if necessary. | - | - | Now: 0% | For most projects, a proper layout.tsx file should be created from the getLayout function pattern. | | C9 | Create an error.tsx page for every route, if necessary. | - | - | Now: 0% | This step is optional for every route.

Follow the guide here: https://nextjs.org/docs/app/building-your-application/routing/error-handling | | C10 | Remove the pages directory. | App Directory Boilerplate (partially) | vscode://intuita.intuita-vscode-extension/showCodemod?chd=nARTEpqaNCsnGw3tnJN6B45fMB0 | Now: 25% | After you have migrated all pages from the pages directory to the app directory, you can remove the pages directory. | | A1 | Extract code blocks and re-export as GET, POST, etc. | Replace Route Handlers | | Now: 0% Soon: 80+% | this step can occur at any order. should this be part of migrator or optimizer? | | A2 | Replace res and req with corresponding NextRequest and NextResponse objects | Replace Route Handlers | | Now: 0% Soon: 80+% | this step can occur at any order |


Recommendations to Improve upgrade guide

Sections/considerations of a comprehensive guide