Migrating from CRA (create-react-app) to Next.js

Published January 7, 2021Last updated March 22, 20233 min read

I have recently migrated the React app bootstrapped with create-react-app to Next.js. The main reason was to improve SEO by making the app more indexable with Next.js, which enables server-side rendering.

This blog post will cover the necessary steps in the migration process.


  • next package (version 13) should be installed
  • @next/eslint-plugin-next package should be installed as a dev dependency

Npm scripts

There should be three required scripts in package.json.

  • build builds the app for production usage (the app is built in .next directory).
  • dev runs the development server on the given port.
  • start runs the production server on the given port.
"scripts": {
"build": "next build",
"dev": "next dev -p 1234",
"start": "next start -p 1234"

Environment variables

Environment variables should be prefixed with NEXT_PUBLIC_ so they can be used in the browser. dev and start scripts can use variables defined in .env.local and .env.production.local files, respectively.

// .env.local


Update the eslint configuration to include the Next.js eslint plugin.

// .eslintrc.js
module.exports = {
extends: ['plugin:@next/next/recommended'],
parserOptions: {
ecmaFeatures: {
jsx: true
ecmaVersion: 2022,
sourceType: 'module'

Head tags

Page-specific meta tags should be stored in the component function between Head (imported from next/head) tags.

Common link tags should be stored in the component function in pages/_document.js between Head (imported from next/document) tags.

Put viewport and charset meta tags separately between Head (imported from next/head) tags with specified key attributes. With this approach, the default values will be changed.

Other meta tags should follow the same principle as common link tags.

<meta key="charset" charSet="utf-8" />
content="width=device-width, initial-scale=1"

Routing and pages

Pages are associated with a route based on their file name, e.g., pages/home.jsx is mapped to /home. The default pages directory (./pages) can be changed to ./src/pages.

Implement a custom Not found page in the pages/404.js file. Replace the Link component from the React router with the Link component from the next/link.

Service worker

A service worker can be registered in the App component from pages/_app.js file using the useEffect hook. Store it in the public folder.

function App({ Component, pageProps }) {
useEffect(() => registerServiceWorker(), []);
return <Component {...pageProps} />;

Third-party library CSS

Import external CSS at the beginning of the pages/_app.js file.

import 'bootstrap/dist/css/bootstrap.min.css';

State management

This topic is covered in State management with Next.js and React post.

Code example

Here is the link to the repository with a code example.


© 2023