Gatsby to Next.js migration
By Pieti Kinnunen
January 22nd, 2025
Migrating from Gatsby to Next.js can be a great choice for modernizing your website and making your website better fit your needs. Both frameworks are based on React, so many of your existing components should migrate quite easily. However, there are significant differences in routing, data fetching, and static asset handling that you’ll need to address. Here’s a guide to help you make the transition simple.
Table of contents
- In this post:
Getting Started
Next.js has two approaches for their routing: Pages Router and App Router. For this migration, I would go with the newer App Router over the previous pages router, as it is the recommended way of structuring Next.js applications and the Next.js team will likely offer support for it longer than the older Pages Router. You’ll also be able to leverage the newest React features, such as server components, with the App router.
To begin, you can either create a new Next.js project or update your existing code to use Next.js instead of Gatsby. I’ll briefly go over both setup methods
Creating a new project
You can create a new Next.js project either by using the npx create-next-app@latest
-command, which guides you through options for your project and sets up boilerplate files.
The other method would be to create the project and files manually from scratch is to use npm install next@latest react@latest react-dom@latest
to install the required dependencies. After this you should update the scripts section in package.json
to look like:
{"scripts": {"dev": "next dev","build": "next build","start": "next start"},}
After this you'll need to create the needed files yourself, for example the app directory and config files.
Updating your existing code
Alternatively, if you want to reuse the existing directory of your Gatsby project you'll need to pretty much do the same steps as with manually creating a new Next.js project:
Remove all Gatsby dependencies from your package.json.
Update the scripts section in package.json to look like:
{"scripts": {"dev": "next dev","build": "next build","start": "next start"},}
Install Next.js and its required dependencies using:
npm install next@latest react@latest react-dom@latest
After these steps you can move on to the next steps
Creating Routes
Both Gatsby and Next.js use file-system routing, which means the routes in your application are determined by how you structure your files, eg. src/pages/page-slug/index.js
in Gatsby can be accessed at www.your-site.com/page-slug and the same address in Next.js would be the file src/app/page-slug/index.page.js
.
Moving your static pages over from Gatsby is simple; you should be able to just move them into the Next.js app directory.
Dynamic Routes: In Gatsby, dynamic routes are created using the createPages API, whereas in Next.js, you define them directly in the file name using square brackets.
For example: Next.js: src/app/[slug]/page.js.
To fetch the slugs that'll be used for creating these routes, implement the generateStaticParams
function in your dynamic route file. For example:
export async function generateStaticParams() {const slugs = await fetchSlugs();return slugs.map((slug) => ({ slug: slug }));}
With this function you can get the slugs from wherever you need, eg. create them from markdown files in your codebase or fetch them from a CMS. The word "slug" in the directory name can be replaced with any word, you'll just need to make sure your generateStaticParams returns an array of objects with a key of the same name.
Creating Pages
In Next you can create a layout.tsx file in the root of the app directory to include data or components on all pages that are included in that directory. In the layout you should include shared meta tags, scripts and for example your header and footer. Similar layout wrappers can be created on lower directories as well if you want to have some shared data only on specific routes.
Internal routing
You need to convert your Gatsby internal link components to use Next's Link component. There isn’t much difference between them so the change should be as simple as changing the import from “import { Link } from 'gatsby’
” to “import Link from ‘next/link’
” and changing the link destination definition from “to=‘destination’
” to “href=‘destination’
”.
// Gatsby<Link to="/about">About</Link>// Next.js<Link href="/about">About</Link>
Data Fetching
Gatsby uses useStaticQuery to fetch data at build time and on the client you need to use React's useEffect. In the Next.js App Router you can leverage React server components that can fetch data when they need it with basic fetch requests.
No node APIs or source plugins are needed in Nextjs. For static page content convert useStaticQuery to just an async fetch in the page or in individual components. Nextjs will automatically cache the requests and their result so the queries only need to be re-run if you've specified a revalidation time for them, or if using on-demand revalidation with webhooks or similar.
Here's an example of fetching data in Next.js for a page:
export const Page = async ({ params }) => {const data = await fetchDataFromDatabase(params.slug);return (<Render the page and components here>);};
The params include data from the router, for example the previously mentioned getStaticParams passes the slug here which can be used to query your database among other things.
You can also fetch data for individual components in the same way. These fetches are happening only on the server, so they can for example be authenticated without fear of exposing secret tokens to clients. If you need to fetch data on client side, you can still use the same useEffect approach as with Gatsby.
Images
In Gatsby, images are loaded and optimized with the gatsby-image component. Next.js has its own built-in next/image component for loading and optimizing the images. The syntax for them is a bit different. Next.js Image component is used like <Image src={image-source} width={width} height={height} alt="image alt text here" />
SEO Metadata
Both Gatsby and Next.js have built-in Head components that can be used for SEO meta tags. In Next you can import from it next/head and then wrap your meta tags in <Head>. This component can be included in the root layout to include the tags in all pages, and for individual pages you can use the <Head> individually if needed.
Static folder
Lastly you should move your static assets. Next.js uses the public folder for static assets. Gatsby does the same thing with the static folder, so you just need to rename your "static" folder to "public".
Conclusion
After migrating your pages, routes, and assets, you should of course test your application thoroughly. Validate that:
All routes resolve as expected
Data fetching and caching works as expected
Static assets are served from the public folder.
Internal links and SEO tags are correctly configured.
This blog post gave you the basic frame for migrating from Gatsby to the more modern and performant Next.js.
If you are planning on migrating your website to Next.js or are looking to build a new site from scratch, feel free to contact us using the form below!
Contact us
Get in touch and let's discuss your business case
Submitting this form will not sign you up for any marketing lists. Your information is strictly used and stored for contacting you. Privacy Policy