Vercel Redirects After WordPress → Hugo Migration (94% Link Recovery)
WordPress migration broke old URLs. vercel.json regex redirects preserved 94% of inbound links per Google Search Console.
Migration: /?p=123 WordPress → /posts/slug/ Hugo on Vercel
Week 1: 404 errors in GSC jumped to 1,200/day
TL;DR
- Map old URL patterns to new paths with vercel.json redirects.
- Use regex captures for date-based WordPress permalinks.
- Verify in GSC Links report after deploy.
Mapping file
Exported WordPress redirects CSV → generated JSON:
{
"redirects": [
{ "source": "/hello-world/", "destination": "/posts/hello-world/", "permanent": true },
{ "source": "/category/javascript/", "destination": "/tags/javascript/", "permanent": true }
]
}
200 entries — under Vercel limit but unwieldy.
Regex for date-based URLs
Old pattern: /2024/03/my-post/ → new: /posts/my-post/
{
"redirects": [
{
"source": "/:year(\\d{4})/:month(\\d{2})/:slug",
"destination": "/posts/:slug",
"permanent": true
}
]
}
Note double backslashes in JSON for \d.
Rewrite for client-side SPA (not my case)
Don't confuse redirect with rewrite:
{ "source": "/app/:path*", "destination": "/app/index.html" }
That's for SPAs. Blogs want 308 permanent redirects for SEO.
Trailing slash trap
/posts/hello → 404
/posts/hello/ → 200
Hugo uses trailing slashes. Add:
{ "source": "/posts/:slug", "destination": "/posts/:slug/", "permanent": true }
Test before deploy
npx vercel dev
# curl -I http://localhost:3000/2024/03/old-post
# HTTP/1.1 308 Permanent Redirect
# Location: /posts/old-post/
GSC result after 3 weeks
404 count dropped 1,200 → 80/day. Remaining were external bad links, not migration.
Bulk generate redirects from CSV
// scripts/wp-to-vercel.mjs
import fs from 'node:fs';
const rows = fs.readFileSync('redirects.csv', 'utf8').trim().split('\n').slice(1);
const redirects = rows.map(line => {
const [from, to] = line.split(',');
return { source: from.trim(), destination: to.trim(), permanent: true };
});
fs.writeFileSync('vercel.json', JSON.stringify({ redirects }, null, 2));
Run once during migration — don't hand-edit 200 rules.
Limit
Vercel supports 1,024 redirects per project on Hobby. Split across vercel.json + _redirects if needed.
FAQ
How do I redirect old WordPress URLs on Vercel?
Use vercel.json redirects array with source patterns matching old permalinks and destination new paths.
Do Vercel redirects preserve SEO?
301 redirects pass most link equity. Monitor GSC for 404 spikes after migration.
Can I use regex in Vercel redirects?
Yes — source supports regex with capture groups: /blog/(\d{4})/:slug → /posts/:slug.