Headless WordPress, Zero URL Changes: How We Moved the Cuelinks Blog
Headless WordPress, Zero URL Changes: How We Moved the Cuelinks Blog
The Cuelinks blog has about 180 posts and years of search rankings behind them. Moving it to a modern front end is easy to imagine and easy to get badly wrong. One changed URL, one missing canonical tag or one wrong redirect, and traffic that took years to earn can quietly disappear.
So we set ourselves one rule at the start: zero URL changes, and a rollback we could trust. This is how it went, including the mistakes we nearly shipped.
What we built
WordPress is still where our writers work. What changed is who builds the pages visitors see.
WordPress moved to a private address that only company staff can reach, protected by Cloudflare Access. It no longer serves public pages, and it is no longer exposed to the internet at large.
A fast front end built with Astro, running on Cloudflare Workers, reads content from WordPress through its API and renders every page. Finished pages are cached at the edge.
A small router sits in front. Pages go to the new front end. Things only WordPress can produce, such as images, sitemaps, RSS feeds and scheduled-post jobs, still go to the old path, untouched.
Editors publish exactly as before. A short notification tells the front end to refresh its cache, so changes normally appear within about a minute.
The rule: zero URL changes
Keeping every address identical sounds simple. It means matching slugs, trailing slashes, nested category paths, tag and author pages, pagination, 404 behaviour and redirects, and not letting the new system invent URLs the old one never had. We decided not to trust our own eyes on any of it.
What almost went wrong
None of these would have crashed the site. All of them would have hurt it quietly.
| What we nearly shipped | Why it would have hurt |
|---|---|
| 12 posts per page instead of 10 | Every numbered page would have held different posts than before, and the last three pages would have returned 404. |
| Our own links marked nofollow | The SEO plugin sat on the new private address, so it treated our own domain as an outside site. Nearly every internal link would have gained nofollow and opened in a new tab. |
| Pages served from a stale cache | After a release, old pages would have kept appearing. We made every release start with a clean cache. |
| Server code published as a file | The build output included our server bundle, and our tooling refused to publish it as a public asset. A one-line ignore file fixed it. |
| A literal “&” in author bios | WordPress hands over some text with HTML codes still inside. Our comparison caught “earn & save” before readers did. |
| Author email addresses on every post | The old author box printed work emails. We deliberately did not rebuild that. |
How we proved it
We never judged the result by looking at pages. We crawled 398 addresses on the old and the new site: every post, category, tag and author page, and every numbered page. For each pair we compared the status, title, description, canonical address, robots setting, headings, structured data, images, links and the text of the article itself.
That comparison is what found the pagination mismatch, the nofollow problem and the “&” bug. By the end, every remaining difference was one we had chosen on purpose, such as a hidden main heading on the home page.
Fast, and still fresh
Cached pages come back in around a tenth of a second in our tests. The harder problem is not caching, it is knowing when to throw the cache away. Each cached page is keyed to the release it came from and to a version number. When an editor publishes, WordPress bumps that version, and every page refetches itself on its next visit. No one has to purge URLs by hand.
A rollback we could trust
Before launch we wrote the rollback down, along with a smoke test of 26 checks to run right after. If anything breaks, we delete one route in Cloudflare and traffic goes back to the old path in about a minute. The original path to WordPress was left exactly as it was, so there is nothing to repair afterwards.
How we built it
We built this working side by side with Claude Code, the same kind of tooling we describe in Project Foundry. It was useful for writing the crawler and the routing tests quickly. It did not replace the part that matters: deciding what to measure and refusing to ship until the numbers agreed.
Do it yourself
We turned what we learned into a practical, SEO-safe guide with tested example code, and published it for anyone planning the same move. It covers when headless is a bad idea, the nine steps, the gotchas above in more detail, and a launch checklist.
If you are considering this for your own site, our advice is short: decide on zero URL changes first, measure everything against the old site, and write the rollback before you need it.