You have a marketing site that has outgrown its tool, and someone has suggested you migrate to Next.js with a headless CMS such as Sanity. In many cases that is a good idea. But the risky part of a migration is almost never the code. It is the pages that vanish without a redirect, and the updates your team can see while visitors cannot.
I write about it because I use this stack every day. In May 2026, I rebuilt the marketing site of Moonworkers, my own company, in Next.js and Sanity. This site is built the same way, and my content machine publishes to it directly. Here is what I check before switching over, in the order I do it.
01What changes with a Next.js and Sanity site
A traditional site mixes content and layout in the same tool. With a headless CMS, you separate them. Sanity stores structured content: an article has a title, a summary, a body, an image, an FAQ. Next.js reads that content and builds the pages. The people who write never touch the code, and whoever codes never touches the copy.
Sanity provides an official package for this, next-sanity, which brings together the client, visual editing and the option of embedding the Studio inside the application itself (Sanity documentation on Next.js). On this site, the Studio lives at /studio, in the same project. I should add that Sanity recommends deploying the Studio on their side instead. For a site where I write alone, the embedded Studio suits me; for a larger editorial team, I would follow their advice.
In practical terms, here is what you gain: bespoke templates, fast pages, and content you can reuse elsewhere (an app, an email, another language). What you lose is the freedom to change everything without a developer.
02When the migration is not worth it
I would rather say this before anything else. If your marketing team edits the layout itself every week, drops in sections and tests home page variants without asking anyone, a visual tool such as Webflow does that job very well. Moving from Webflow to Next.js takes that autonomy away, and you need a real need on the other side for the trade to make sense.
The cases where I think the migration is justified:
- the site has to carry something closer to a product, like the Moonworkers calculators, which I wanted to write and test as code (I told that story in the article on verified online calculators);
- content is published by an automated tool, which is my case, and you need a clean write API;
- the site exists in several languages, with content linked across them;
- you have someone, in-house or outside, to maintain the code over time.
If none of these rings a bell, keep your tool and improve what you have. A migration costs time, and it moves your search rankings around for weeks, even when it is done well.
03List every URL before writing a line of code
Google puts it very simply: it indexes page by page. In a short Google Search Central video, John Mueller explains that a page whose address changes must pass its signals on to the new one, otherwise they are lost, and that any URL change is a migration, from a full rebuild to simply removing the trailing slash (Do URL structure changes affect SEO?). He advises drawing up the list of old and new URLs before you start.
Google's documentation on site moves and migrations says the same: start with the most important pages and map each one to its destination. That document is what I call the URL map, and it is the first deliverable of a migration, before the mock-up.
How I build the URL map
- I export every known URL: the current sitemap, the pages seen in Search Console, those in the analytics tool, and the links found by crawling the site.
- I put them in a spreadsheet, one row per URL, with a "new address" column and a "decision" column (keep, redirect, remove).
- I keep the address unchanged whenever I can. A URL that does not change needs no redirect at all.
- For each page I remove, I look for the closest page by topic, not the home page.
- I have the map reviewed by the person who knows the content, because they know which pages matter to customers.
The map is then used three times: to write the redirects, for acceptance testing, and for monitoring after the switch.
04Writing permanent redirects in Next.js
Google recommends permanent server-side redirects, as 301 or 308, and advises against JavaScript redirects when the server can do the job (Google Search Central, Redirects and Google Search). Next.js lets you declare them in its configuration file, with the "redirects" key (Next.js documentation). Each redirect needs three fields:
- "source", the old address, for example /about-us;
- "destination", the new one, for example /en/about;
- "permanent", set to true for a lasting redirect.
With "permanent" set to true, Next.js returns a 308, which browsers and search engines remember. Do not worry if you never see a 301: for Google, 301 and 308 both signal a permanent move. A pattern such as /blog/:slug to /en/blog/:slug saves you writing one line per article when a whole section changes prefix.
There are three mistakes I check for every time. Chains, where A points to B which points to C: I point each old URL straight at its final destination. Mass redirects to the home page, which Google's documentation advises against. And duration: Google asks you to keep redirects for as long as possible, at least a year. In a version-controlled configuration file, they cost nothing to keep.
05The cache, or why your team does not see what visitors see
This is the part specifications tend to forget. Next.js caches the pages it has already produced. When someone publishes in Sanity, the live page does not change until that cache has been refreshed.
On one assignment, I saw a site that looked fine to the logged-in team and was broken for visitors, because of a cache. Since then, I always check as a visitor would: a private window, no session, on the public address.
Next.js provides a function to refresh a path on demand, revalidatePath, which you can call from a route on the site (Next.js documentation). Called from a route, it marks the page, which is regenerated on the next visit. Sanity, for its part, describes several strategies (time-based, tag-based or path-based) plus webhooks to trigger revalidation on each publication.
On this blog, I chose the one that is easiest to verify. My content machine publishes the article to Sanity, calls a revalidation route protected by a secret, then loads the page once. After that, I check the public page, in French and in English: a 200 response, the image, the headings, the sources. I described that publishing bottleneck in automating publishing before producing more.
06Where to start your migration
If you are thinking of migrating to Next.js and Sanity, this is the order I would follow on Monday:
- Write one page on why you are migrating. If the reason boils down to "the site is old", go back to the section on when it is not worth it.
- Build the URL map and have it reviewed.
- Model the content in Sanity from your real pages, not from an ideal mock-up.
- Write the redirects from the map, and decide how the cache refreshes on each publication.
- Run acceptance testing on the staging address, map in hand; my acceptance testing and go-live checklist can serve as a starting point.
- After the switch, follow your pages in Search Console for several weeks. Google warns that rankings can fluctuate; an automated SEO report stops you forgetting to look.
I cannot promise a migration without any dip: even well prepared, it asks Google to look at everything again. Preparation reduces what can break, and that is already a lot. If you would like to look at your case together, the services page explains how I work; we can talk it through.
