Article
Migrating from Gatsby to Next.js
I built my first portfolio site with Gatsby in 2019 and shipped a bunch of client work on it through 2020-2021. It was the obvious choice at the time — React, GraphQL data layer, plugin ecosystem, fast static output. By early 2023 I’d had enough.
This is a short reflection on why I migrated to Next.js, what I lost, and what I gained.
What was good about Gatsby
- GraphQL data layer. Once you got past the learning curve, querying images, markdown frontmatter, and remote APIs through a single GraphQL schema was elegant.
gatsby-image/gatsby-plugin-image. Best-in-class image handling for the era. Lazy loading, blur-up placeholders, responsive srcsets — all by default.- Plugin ecosystem.
gatsby-source-wordpress,gatsby-source-contentful,gatsby-transformer-remark— for content sites, the plugins did 80% of the work.
What stopped working
A few things piled up:
- Build times. A 200-page site that took 30 seconds in 2020 was taking 5+ minutes by 2022. Each plugin added overhead. Each MDX file was a parse hop. Editing a typo and waiting two minutes for the dev preview to rebuild was death.
- Plugin churn. Plugins fell behind core upgrades; I’d hit version mismatches three times a year. By Gatsby v4/v5, several of my plugins had stopped working entirely.
- Image plugin breakage.
gatsby-plugin-imageshipped a major rewrite. My oldImgandGatsbyImagecalls all needed migration. Same week, the plugin started erroring on certain SVGs. - The DSG / SSR confusion. Gatsby tried to add server-rendered
modes (DSG, SSR) to compete with Next.js. The configuration surface
exploded; the docs lagged. I spent a Saturday trying to understand
what
flags.PARTIAL_HYDRATIONdid and emerged with no useful answer. - Release cadence. Next.js was shipping every few weeks; Gatsby felt like it was holding ground. Vercel’s funding asymmetry against Gatsby Inc. became impossible to ignore.
What Next.js offered (in 2023)
Next.js 12-13 was where I made the jump. The Pages Router was still the recommended path; the App Router had just landed in beta and was clearly not ready.
What pulled me over:
getStaticProps/getStaticPathswere simpler than Gatsby’s GraphQL layer for static sites. Yes, you lose the unified schema. But for most projects, you don’t need a schema — you need a function that returns props.next/image. Caught up togatsby-plugin-image. Easier API for most cases.- Build times. ~3× faster on my biggest site. Fewer plugin layers.
- Vercel deploy. One git push, one preview URL, one production URL. Not a Gatsby fault per se — just much more polished.
What I lost
- The GraphQL data layer. For a site that aggregated WordPress + Contentful + local markdown, I had to write three separate fetch helpers. Manageable but uglier.
- Some image polish.
gatsby-plugin-image’s art-direction support was better thannext/image’s. Most sites don’t need it. - Confidence in image processing.
next/image’s on-demand transform pipeline broke a few times in early Next.js 13.
What I’d tell myself in 2023
- The migration takes longer than you think. Budget two weekends, not one.
- Don’t try to keep Gatsby’s GraphQL schema mental model; rewrite the
data flow with
getStaticPropsfrom scratch. - Don’t migrate during a Next.js major version transition. I started during Next 12 and was on Next 13 by the time I finished. Things broke in interesting ways.
- The single biggest win wasn’t features — it was maintenance burden. A simpler stack with one big sponsor beat a more elegant stack with a fading one.
(Three years later, I’ve left Next.js too — but that’s a separate post.)