If you want to move your existing Create React App to Next.js and keep a Single-Page App, you can move your old application's entry point to an Optional Catch-All Route named pages/[[...app]].js.

// pages/[[...app]].js

import { useState, useEffect } from 'react'
import CreateReactAppEntryPoint from '../components/app'

function App() {
  const [isMounted, setIsMounted] = useState(false)

  useEffect(() => {
    setIsMounted(true)
  }, [])

  if (!isMounted) {
    return null
  }

  return <CreateReactAppEntryPoint />
}

export default App
If you want to move your existing Create React App to Next.js and keep a Single-Page App, you can move your old application's entry point to an Optional Catch-All Route named pages/[[...app]].js.

// pages/[[...app]].js

import { useState, useEffect } from 'react'
import CreateReactAppEntryPoint from '../components/app'

function App() {
  const [isMounted, setIsMounted] = useState(false)

  useEffect(() => {
    setIsMounted(true)
  }, [])

  if (!isMounted) {
    return null
  }

  return <CreateReactAppEntryPoint />
}

export default App
Most Create React App examples use react-helmet to assist with adding meta tags for proper SEO. With Next.js, we use next/head to add meta tags to your element. For example, here's an SEO component with Create React App:

// src/components/seo.js

import { Helmet } from 'react-helmet'

export default function SEO({ description, title, siteTitle }) {
  return (
    <Helmet
      title={title}
      titleTemplate={siteTitle ? `%s | ${siteTitle}` : null}
      meta={[
        {
          name: `description`,
          content: description,
        },
        {
          property: `og:title`,
          content: title,
        },
        {
          property: `og:description`,
          content: description,
        },
        {
          property: `og:type`,
          content: `website`,
        },
        {
          name: `twitter:card`,
          content: `summary`,
        },
        {
          name: `twitter:creator`,
          content: twitter,
        },
        {
          name: `twitter:title`,
          content: title,
        },
        {
          name: `twitter:description`,
          content: description,
        },
      ]}
    />
  )
}
Here's an example package.json:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  }
}
A recommended way of accessing Web APIs safely is by using the useEffect hook, which only executes client-side:

import { useEffect } from 'react'

useEffect(() => {
  // You now have access to `window`
}, [])
Instead of optimizing images at build time, Next.js optimizes images on-demand, as users request them. Your build times aren't increased, whether shipping 10 images or 10 million images.

import Image from 'next/image'

export default function Home() {
  return (
    <>
      <h1>My Homepage</h1>
      <Image
        src="/me.png"
        alt="Picture of the author"
        width={500}
        height={500}
      />
      <p>Welcome to my homepage!</p>
    </>
  )
}
And here's the same example using Next.js.

// src/components/seo.js

import Head from 'next/head'

export default function SEO({ description, title, siteTitle }) {
  return (
    <Head>
      <title>{`${title} | ${siteTitle}`}</title>
      <meta name="description" content={description} />
      <meta property="og:type" content="website" />
      <meta property="og:title" content={title} />
      <meta property="og:description" content={description} />
      <meta property="og:site_name" content={siteTitle} />
      <meta property="twitter:card" content="summary" />
      <meta property="twitter:creator" content={config.social.twitter} />
      <meta property="twitter:title" content={title} />
      <meta property="twitter:description" content={description} />
    </Head>
  )
}
Since Next.js uses pre-rendering, you'll need to safely access those Web APIs only when you're on the client-side. For example, the following code snippet will allow access to window only on the client-side.

if (typeof window !== 'undefined') {
  // You now have access to `window`
}
Rather than using the :slug syntax inside your Route component, Next.js uses the [slug] syntax in the file name for Dynamic Routes. We can transform this to Next.js by creating two new files, pages/blog/index.js (showing all pages) and pages/blog/[slug].js (showing an individual post).

// pages/blog/index.js

export default function Blog() {
  return <h1>All Blog Posts</h1>
}

// pages/blog/[slug].js

import { useRouter } from 'next/router'

export default function Post() {
  const router = useRouter()
  const { slug } = router.query

  return <h1>Post Slug: {slug}</h1>
}
The Link component for performing client-side route transitions is slightly different from React Router.

// Before (React Router)
import { Link } from 'react-router-dom'

export default function App() {
  return <Link to="/about">About</Link>
}

// After (Next.js)
import Link from 'next/link'

export default function App() {
  return (
    <Link href="/about">
      <a>About</a>
    </Link>
  )
}
Most React applications that use React Router have a top-level navigation file, containing a list of routes. For example:

import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'

export default function App() {
  return (
    <Router>
      <Switch>
        <Route path="/about">
          <h1>About</h1>
        </Route>
        <Route path="/blog">
          <h1>Blog</h1>
        </Route>
        <Route path="/">
          <h1>Home</h1>
        </Route>
      </Switch>
    </Router>
  )
}

Recommend

Nextjs Migrating from Create React App Search Engine Optimization

Nextjs Migrating from Create React App Image Component and Image Optimization

Nextjs Migrating from Create React App Safely Accessing Web APIs

Nextjs Migrating from Create React App Updating package.json and dependencies

Nextjs Migrating from React Router Nested Routes

Nextjs Migrating from React Router Basics

Nextjs Incrementally Adopting Next.js Strategies Rewrites

Nextjs Incrementally Adopting Next.js Strategies Subpath

Nextjs CDN Support with Asset Prefix

Nextjs Custom Webpack Config

Nextjs Ignoring TypeScript Errors

Nextjs Static Optimization Indicator

Nextjs Custom Page Extensions Including non-page files in the pages directory

Nextjs Custom Page Extensions

Nextjs Ignoring ESLint

Nextjs Trailing Slash

Nextjs URL Imports Examples Static Image Imports

Nextjs URL Imports Examples Skypack

Nextjs URL Imports

Nextjs Redirects Header, Cookie, and Query Matching Redirects with i18n support

Nextjs Redirects Header, Cookie, and Query Matching Redirects with basePath support

Nextjs Redirects Header, Cookie, and Query Matching

Nextjs Redirects Path Matching Regex Path Matching

Nextjs Redirects Path Matching Wildcard Path Matching

Nextjs Redirects Path Matching

Nextjs Redirects

Nextjs React Strict Mode

Nextjs exportPathMap Customizing the output directory

Nextjs exportPathMap Adding a trailing slash

Nextjs exportPathMap

Nextjs Rewrites Rewriting to an external URL Rewrites with i18n support

Nextjs Rewrites Rewriting to an external URL Rewrites with basePath support

Nextjs Rewrites Rewriting to an external URL Incremental adoption of Next.js

Nextjs Rewrites Rewriting to an external URL

Nextjs Rewrites Header, Cookie, and Query Matching

Nextjs Rewrites Path Matching Regex Path Matching

Nextjs Rewrites Path Matching Wildcard Path Matching

Nextjs Rewrites Path Matching

Nextjs Rewrites Rewrite parameters

Nextjs Rewrites

Nextjs Disabling ETag Generation

Nextjs Headers Header, Cookie, and Query Matching Cache-Control

Nextjs Headers Header, Cookie, and Query Matching Headers with i18n support

Nextjs Headers Header, Cookie, and Query Matching Headers with basePath support

Nextjs Headers Header, Cookie, and Query Matching

Nextjs Headers Path Matching Regex Path Matching

Nextjs Headers Path Matching Wildcard Path Matching

Nextjs Headers Path Matching

Nextjs Headers Header Overriding Behavior

Nextjs Headers

Nextjs Disabling HTTP Keep-Alive

Nextjs Environment Variables

Nextjs Setting a custom build directory

Nextjs Configuring onDemandEntries

Nextjs Disabling x-powered-by

Nextjs Runtime Configuration

Nextjs Compression

Nextjs Build indicator

Nextjs Base Path Images

Nextjs Base Path Links

Nextjs Base Path

Nextjs next.config.js

Nextjs Configuring the Build ID

Nextjs getStaticPaths getStaticPaths with TypeScript

Nextjs getStaticPaths getStaticPaths return values Fallback pages

Nextjs getStaticPaths getStaticPaths return values fallback: false

Nextjs getStaticPaths getStaticPaths return values paths

Nextjs getStaticPaths

Nextjs getServerSideProps getServerSideProps return values getServerSideProps with TypeScript

Nextjs getServerSideProps getServerSideProps return values redirect

Nextjs getServerSideProps getServerSideProps return values notFound

Nextjs getServerSideProps getServerSideProps return values props