The redirect map
WordPress to Next.js Redirects: Build the Map, Choose the Status Code, Test Every Line
Nobody frames a redirect map and hangs it in the lobby. It is still the file that decides whether a WordPress to Next.js migration keeps its traffic. Every bookmark, backlink and ranking points at an old address, and each one needs a single, permanent answer.
October 8, 2026 · 9 min read
The short answer
List every old URL from your sitemaps, a crawl, Search Console, backlinks, server logs and any redirect plugin. Give each a destination, flatten old chains to one hop, and use permanent redirects, which Next.js sends as 308 and Google treats like a 301. Put patterns in next.config, move very large maps into Proxy, and test the full list before DNS changes.
On this page
- The most valuable file in the whole migration
- Six sources for the old side of the map
- The redirects your old plugins were quietly running
- 301, 308 and the status code Next.js sends
- next.config or Proxy: where a big map should live
- Chains, loops and redirects to nowhere useful
- Testing the map before and after DNS moves
- Redirect work by theme and by site type
The most valuable file in the whole migration
A new site gets judged on its design. A migration gets judged on whether the phone keeps ringing in the month after launch. Most of that comes down to one spreadsheet: old URL in column A, new URL in column B. If a page moved and the map does not say where, Google finds a 404, the link equity that page collected stops flowing, and a customer clicking an old link from a directory or an email lands on nothing.
The good news is that the work is mechanical. The bad news is that it is easy to underestimate. A WordPress site exposes many more URLs than it has pages, as the URL structure guide explains. Keeping your existing addresses wherever you can shrinks the map, because a URL that does not change needs no redirect. What remains is the list of real changes, and it deserves the same care as the code.
A redirect you forgot is a page you deleted.
Six sources for the old side of the map
No single tool sees every URL that matters. Sitemaps list what the SEO plugin thought was important. Crawlers find what is linked. Search Console shows what Google actually sends people to. Backlink data shows what other sites point at, including pages you deleted in 2019. Pull all of them and merge the list.
- XML sitemaps from Yoast, Rank Math or whichever SEO plugin generated them, including the separate post, page, category and product sitemaps.
- A full crawl of the live site, which turns up archives, paginated pages and attachment URLs the sitemaps skip.
- Search Console's Pages and Performance reports, filtered to URLs with impressions or clicks in the last 16 months.
- Backlink data listing the pages other sites link to, including ones that already 404 and could be rescued.
- Server or CDN logs, which show the URLs real visitors and bots request, typos and all.
- Your existing redirect table, whether it lives in a plugin, an .htaccess file or the host's control panel.
Give each row the same columns: old URL, new URL, status, source and a one-line reason. The reason column feels like bureaucracy until someone asks, a year later, why the old pricing page goes to the contact page.
The redirects your old plugins were quietly running
Most WordPress sites older than a few years already run redirects nobody remembers creating. The Redirection plugin keeps them in its own table and, according to its documentation, exports them as CSV, JSON, Apache .htaccess rules or Nginx rewrite rules. Rank Math and Yoast Premium have redirect managers of their own. Some hosts add rules at the server level. All of them stop working the moment WordPress is switched off.
Export every one of them and treat the export as part of the map. Then check three things. First, does the rule still point somewhere real, or does it send people to a page that has itself been deleted? Second, is it a regular expression? Redirection marks regex rules with a flag, and Next.js uses path-to-regexp syntax, which is close but not identical, so each pattern gets rewritten and tested rather than pasted. Third, is it a 302? Plenty of plugin rules were created as temporary and left that way for years. If the move was permanent, the new rule should say so.
301, 308 and the status code Next.js sends
WordPress plugins usually issue 301s. Next.js issues 308s. The redirects option in next.config takes a permanent flag: true sends a 308, false sends a 307. The Next.js documentation explains why. Browsers historically changed POST requests to GET when following a 301 or 302, and 307 and 308 exist to preserve the original method.
For search, the difference does not matter. Google's documentation groups 301 and 308 together as permanent redirects and says the indexing pipeline uses them as a signal that the target should be canonical. Temporary codes, 302 and 307 included, do not carry that signal. So the rule is simple: anything that moved for good gets permanent: true. If some old client or partner integration insists on a 301, Next.js accepts a statusCode property instead of permanent, though not both on the same rule.
Two more details from the Next.js docs are worth knowing. Query strings pass through to the destination, so /old-post/?utm_source=newsletter arrives at /new-post/?utm_source=newsletter with its tracking intact. And redirects are checked before the filesystem, which means a redirect rule will win over a page at the same path. That is helpful when you mean it and confusing when you do not.
The third option
Athena CMS, with AI agents on staff.
Not a theme and not a blank Next.js repo. The content system we put behind every custom site: plain fields, a real preview, every version kept, and AI agents that handle the chores a plugin only nags you about.
- PicassoImages
- ApolloSite analysis
- AresCompetitor watch
- PrometheusContent holes
- AtlasPage depth and structure
- DelphiAI search visibility
and 12 more agents. Two come with Athena; the rest are monthly add-ons.

next.config or Proxy: where a big map should live
There is more than one place to put redirects in a Next.js project, and the right one depends on how many rules you have and how often they change.
| Good for | Limits | Changes need | |
|---|---|---|---|
| redirects in next.config | Known lists and patterns, a few hundred rules | Vercel caps config redirects at 1,024 | A rebuild and deploy |
| Pattern rules | Whole URL families, such as date folders | Patterns must be written and escaped carefully | A rebuild and deploy |
| Proxy with a lookup | Thousands of one-to-one rules | Runs on requests, so lookups must be fast | A data update, no redeploy if stored outside the build |
| Host or CDN rules | Domain-level moves, http to https, www | Separate from the codebase | A change in the host's dashboard |
Patterns do most of the heavy lifting. If every post moves from /2023/04/slug/ to /blog/slug/, one rule with a source of /:year(\d{4})/:month(\d{2})/:slug and a destination of /blog/:slug replaces hundreds of lines. The docs warn that characters such as parentheses, colons and question marks are special in a source and must be escaped when you mean them literally, and that forgetting the slash before a parameter can cause infinite redirects.
For maps beyond about a thousand one-off rules, the Next.js redirecting guide recommends a custom solution in Proxy, the file that Next.js 16 renamed from middleware. The map lives in a JSON file or a fast key-value store, Proxy checks each request against it, and the guide even shows a Bloom filter to avoid loading the full list on every request. Proxy runs after the config redirects, so the two can be combined: patterns in config, the long tail in Proxy.
Chains, loops and redirects to nowhere useful
Google's site move guidance asks for short chains, ideally no more than three hops and fewer than five, and notes that each hop adds latency. Our standard is one. After the map is drafted, resolve every destination: if column B is itself an old URL with its own redirect, replace it with the final address. Repeat until nothing points at something that moves.
Loops are the other failure. They usually come from two rules that disagree, often a trailing slash rule fighting a hand-written redirect, and they show up in the browser as too many redirects. Matching the old trailing slash style in next.config prevents most of them before they start.
Then resist the shortcut of sending every leftover URL to the home page. A redirect to an unrelated page tells Google nothing useful, and Search Console often reports such URLs as soft 404s. If a page had no traffic, no links and no close replacement, an honest 404 is the cleaner answer. If it had value, find the nearest real match: the category, the service or the newer article that covers the same question.
Testing the map before and after DNS moves
- 1
Replay every old URL on staging
Run the full list against the preview build with a crawler or a short script. Each URL should return 200 or exactly one permanent redirect.
- 2
Check the destination, not just the code
A 308 to the wrong page passes a status check and still loses the ranking. Compare final URLs against column B.
- 3
Test query strings and odd cases
Try campaign parameters, uppercase letters, missing trailing slashes and encoded characters, which old links contain more often than you would expect.
- 4
Switch DNS and replay again
Run the same list against the live domain within the first hour. Host and CDN rules sometimes behave differently from staging.
- 5
Watch Search Console and the logs
Check crawl errors and 404 reports daily for the first weeks and add rules for anything the inventory missed.
- 6
Keep the rules
Google advises keeping redirects for at least a year. We keep them for the life of the site, because old links never fully stop arriving.
On a site that runs Athena CMS, Argus keeps watching for broken links long after the launch checklist is filed, so a missed address shows up as a task instead of a silent loss. The full set of launch checks lives in migrating without losing SEO.
Redirect work by theme and by site type
The size of the map depends on what the old site generated. Builder themes create their own URL families: a Divi migration often includes the project post type, and an Avada migration can include portfolio items and FAQ entries. Lightweight themes such as GeneratePress or Astra add little of their own, so their maps are mostly posts, pages and archives.
Stores are the largest. Product, category, tag and filtered URLs all need decisions, covered in the WooCommerce to Next.js guide. Image files are a separate list again, because files that rank in Google Images have addresses of their own; see migrating WordPress images.
Every rebuild we run in Next.js ships with the map as a deliverable, tested before launch and handed over afterward. Your team edits pages in Athena CMS while the routing rules stay in code, reviewed and tested, which is where a list this important belongs.
Questions people ask before they call
Setting permanent: true in next.config sends a 308, and permanent: false sends a 307. Google treats 308 the same as 301 for indexing, so a 308 passes the same signal. If you need an actual 301 for an older client, Next.js lets you set statusCode on that rule instead of permanent.
Next.js does not publish a hard cap of its own, but platforms can. Vercel, for example, limits config redirects to 1,024. For larger maps, the Next.js docs recommend handling redirects in Proxy with a lookup table, which also lets you change rules without a full redeploy. Pattern rules often shrink a big map to a handful of lines.
Yes, with checking. Export them from the plugin as CSV or JSON, then review each one: remove rules that point at deleted pages, flatten chains, convert 302s that were really permanent, and rewrite regular expressions into the path syntax Next.js uses. We load the cleaned list into next.config or a Proxy lookup and test it.
Google's site move guidance says at least a year, and as long as possible. We keep them permanently. Redirects cost almost nothing to keep in a Next.js build, and old links in emails, directories and forum posts keep arriving for years. Removing them saves nothing and loses visitors.
Usually not. A redirect to an unrelated page does not help Google, and those URLs often show up as soft 404s in Search Console. Send a removed page to its closest real replacement, or let it return a 404 if nothing fits. Our Next.js development team makes that call row by row, using traffic and link data.
Keep reading
- Permalinks, mappedWordPress to Next.js URL Structure: Keep the Addresses Google Already TrustsHow WordPress permalinks, categories, ?p= links, pagination, feeds and attachment pages map to Next.js routes, and which URLs to keep, change or retire.
- SEO-safe migrationMigrate WordPress to Next.js Without Losing SEO: The Checklist That Protects Your RankingsMove from WordPress to Next.js and keep your rankings: the URL inventory, permanent redirects, metadata, schema, internal links, sitemaps and launch checks.
- Astra migration guideAstra to Next.js: Migrate an Astra Site Layer by Layer, Rankings IntactMigrate Astra to Next.js without losing rankings: what happens to astra-settings, Site Builder layouts, Spectra blocks and Elementor pages, step by step.
- Kadence migration guideKadence to Next.js: Moving Kadence Blocks, Shop Kit and MembersKadence to Next.js, step by step: parse Kadence Blocks, map the global palette, rebuild Hooked Elements, move Shop Kit stores and members, keep every URL.
- GeneratePress migration guideGeneratePress to Next.js: Leaving the Cleanest Theme in WordPressGeneratePress to Next.js: why GP sites cost less to move, how Elements, hooks and GenerateBlocks CSS migrate, and the URL plan that keeps your rankings.
- Leaving BlocksyBlocksy to Next.js: Moving the Customizer, Content Blocks and Shop ExtrasMove a Blocksy site to Next.js: Customizer settings, header builder, Content Blocks, Post Types Extra fields and Shop Extra features, mapped one by one.
- Everything in WordPress to Next.jsSee the section
Get a redirect map you can trust
Tell us about your site. We will inventory every old URL, check your existing plugin redirects and show you the map before anything moves.
Which of these sounds like you? (pick any)
Rather talk now? Call (210) 346-0848.
