Wordpress Escape

Home / Guide

War story · from the WPEscape workbench

Migrating 528,315 WordPress Pages to Hugo: What We Learned Building the UC Family

This is the long-form technical companion to the UC family case study. If you are considering escaping WordPress and want the honest post-mortem - the CLS regressions we shipped in the first build, the redirect-loop we found in production, the Cloudflare page-rule that saved the launch - read this one. It is not marketing. It is what one operator wishes another operator had told them.

9 min read 10 sections Built to rank
On this page
  1. Where the whole thing started - an index bleed we could not stop
  2. The build plan - and everything we thought was true that was not
  3. The CLS regression we shipped in the first build
  4. Schema.org across 528K pages - why this ended up the biggest ranking lever
  5. llms.txt - the LLM-search play we did not know we were making
  6. The Cloudflare settings that actually mattered
  7. The 4-tier partitioned rebuild - the operational secret sauce
  8. The results - what changed and what did not
  9. The productization - Stretch LLC and Wordpress Escape
  10. What we would do differently
  11. Frequently asked questions
Quick answer

In five engineering days across April 2026, the 7-brand Unlimited Charters transportation portfolio migrated 528,315 WordPress pages to Hugo, served from Cloudflare's edge. Every URL preserved, every schema block validated, 10x index recovery six months later. What follows is the honest write-up - including everything we got wrong the first time.

01

Where the whole thing started - an index bleed we could not stop

Six months before the migration, Google's index for the Unlimited Charters main brand was dropping about 400 pages a day. Nothing was broken. Search Console showed no coverage errors. Wordfence was clean. The pages were still there, still served 200 OK, still had valid meta.

They just were not ranking anymore. Google was quietly folding thin WordPress-generated doorway content out of the index. The March 2026 spam update accelerated it. By August the count had gone from ~444K spun Gen-1 pages down to ~17K indexed. That is a 96% index collapse on a live corpus.

You cannot "fix" that with a WordPress plugin. The problem was not the words. The problem was the container. Google increasingly treats stacked-plugin WordPress corpora - LiteSpeed + Yoast + Elementor + WooCommerce + a slider + a chat widget + a cache warmer + a form builder - as low-signal-per-byte. Every plugin adds JS the plugin ships without asking. Every plugin adds a database round-trip. Every plugin has a schema opinion that conflicts with every other plugin's schema opinion. The result is a site that looks like real information architecture and to a crawler reads like slurry.

Migration was not a preference. It was triage.

02

The build plan - and everything we thought was true that was not

The plan on paper: crawl the source, generate a 1:1 Hugo output for every URL, wire the redirect map, ship. In practice the first working build had four wrong assumptions baked in.

Assumption 1: "Preserve URLs" means every WordPress path renders in Hugo unchanged. False. WordPress permalink structures rewrite silently. /category/casino-shuttle/ and /casino-shuttle/ both work in WP. In Hugo you have to pick one, redirect the other, and the choice affects thousands of internal links. We spent a full day rewriting internal cross-links in the source markdown so that no page linked to the non-canonical version.

Assumption 2: The 21 WordPress plugins each solved a real problem. Also false. When we inventoried what each plugin actually shipped, roughly a third were doing nothing (installed years ago, never used) and another third were doing something Hugo does natively. LiteSpeed Cache does not need a replacement - Cloudflare is the cache. Yoast SEO's actual value was the schema output; that becomes a Hugo partial and stops being a subscription. Only WPML (multilingual) and WooCommerce (checkout) needed real thinking.

Assumption 3: A single Hugo build could render 528K pages in a reasonable window. Nope. First naive build ran for 11 hours before we killed it. Hugo is fast per page but the memory footprint of holding the full render graph in RAM for 528K pages is not free. Solution was partitioning: split the corpus into 4 tiers (freshest hubs, main service pages, state hubs, deep long-tail) and rebuild each on its own cadence. Full-corpus rebuild now runs in ~7 hours.

Assumption 4: Redirects are simple. The first .htaccess shipped with a rewrite loop nobody caught until it was live. A pattern intended to canonicalize trailing slashes was matching its own target after the first hop. Cloudflare intercepted the loop and served a 526 for about 8 minutes before we caught it. The fix was a lookahead - (?!rental[-/]) instead of (?!rental-) - and it is now a standard step in the Wordpress Escape playbook. Any rewrite target that contains a slash needs the lookahead to include the slash. See how we fix page speed the right way for the broader debugging pattern.

03

The CLS regression we shipped in the first build

PageSpeed on the staging build was clean - 94+ on mobile, CLS 0.02, LCP well under 2.5s. So we shipped. Production PageSpeed came back with CLS 0.31 on mobile. On some templates as bad as 0.42.

Cause: Cloudflare's email obfuscation was rewriting mailto: links post-load and inserting a wrapper span. Every wrapper triggered a tiny reflow. On pages with 8+ contact links, the cumulative shift crossed the threshold and PageSpeed downgraded the score.

Fix took 30 seconds - Cloudflare dashboard → Scrape Shield → Email Address Obfuscation → OFF. But we did not know to look there. On a fresh Hugo site you would never suspect Cloudflare of adding CLS, because you built the HTML to be layout-stable. This is the kind of trap WordPress developers do not warn each other about because on WordPress you never notice the shift under all the other shifts.

Second CLS regression: web font swap. display=swap on the primary font caused a visible reflow at ~200ms. Fix was to preload the font with <link rel="preload" as="font" crossorigin> and to size the fallback font metrics with size-adjust so the swap was imperceptible.

Rule

Test CLS in production, not staging. Cloudflare features that inject content post-load do not appear on a staging origin without Cloudflare in front of it. Every Hugo migration should ship with a 24-hour real-user CrUX watch built into the launch checklist.

04

Schema.org across 528K pages - why this ended up the biggest ranking lever

On WordPress, schema was per-post and inconsistent. Yoast handled some. A custom plugin handled others. Some pages had nothing. In practice, rich results eligibility was a coin toss.

On Hugo, schema is a partial. Every page in every template family gets the same @graph shape: Organization + WebSite + template-specific entity (Service, LocalBusiness, Product for city hubs) + BreadcrumbList + FAQPage where FAQs exist. Validated once, applies to all 528K URLs.

Six months in, the effect on rich results eligibility is dramatic. Every hub page qualifies for FAQ-rich results. Every city page has LocalBusiness markup Google can consume for local pack. Every service page has Service + Offer that shows up in AI overviews. This is not a WordPress plugin subscription - it is 40 lines of Hugo template.

The Stretch LLC productization of this stack ships the same schema partial library to every customer. That is the moat.

05

llms.txt - the LLM-search play we did not know we were making

We wrote a hand-authored /llms.txt at the site root the week we launched. It was a checklist item, not a strategy. Two months later Perplexity, Bing Copilot, Claude and ChatGPT were citing UC pages by name in transportation-related queries.

The mechanism: LLM search engines increasingly use llms.txt the way traditional search uses robots.txt + sitemap.xml combined - as a hand-authored index of what a site is about and what it contains. On WordPress, generating a good llms.txt requires a plugin nobody has written well. On Hugo, it is a single file.

If you are betting your traffic mix on Google alone, you are behind. Roughly 30% of high-intent commercial queries now originate on LLM interfaces. llms.txt is the cheapest lever you can pull to be discoverable there. Every Wordpress Escape migration ships one by default.

06

The Cloudflare settings that actually mattered

Cloudflare has hundreds of toggles. Six of them mattered for this migration:

  1. Cache Level: Cache Everything for the static HTML. Default is bypass on cookies; static HTML has no cookies so this is safe and quadruples cache hit rate.
  2. Browser Cache TTL: 4 hours. Long enough to matter for repeat visitors, short enough that a re-deploy propagates in a session.
  3. Origin Cache Control: Respect. Let Hugo emit its own Cache-Control so hashed assets stay immutable and HTML stays must-revalidate.
  4. Auto Minify: OFF. Hugo already minifies. Double-minify introduced a syntax error in one edge case.
  5. Rocket Loader: OFF. Reorders scripts. Broke schema validation.
  6. Email Address Obfuscation: OFF. See the CLS section above.

Every Wordpress Escape migration includes a Cloudflare configuration audit in the launch checklist. This exact list.

07

The 4-tier partitioned rebuild - the operational secret sauce

528K pages cannot ship on a single Hugo build without pain. The partitioning scheme:

  • Tier 1 - Hubs (~200 pages). Main city hubs, state hubs, homepage. Rebuilt every 6 hours. Any content change here is visible fast.
  • Tier 2 - Service pages (~40K pages). Party bus, wedding, corporate, shuttle, casino. Rebuilt nightly.
  • Tier 3 - State + long-tail Gen 4 (~50K pages). Rebuilt every 48 hours.
  • Tier 4 - Gen 1 spun long-tail (~440K pages). Rebuilt weekly.

Each tier's build has its own flock, its own timeout, its own log, its own alert. If Tier 4 hangs (once because of an Imunify360 signature reload race), Tiers 1-3 keep shipping and only the deep long-tail goes stale. Nothing user-facing degrades.

This is the pattern WordPress cannot do. WordPress rebuilds every page on every request. There is no partitioning; there is only cache invalidation, which is famously the hardest problem in computing.

08

The results - what changed and what did not

Six months post-cutover:

  • Index count: ~17K → ~167K. 10x recovery.
  • PageSpeed mobile: ~40 average → 90+ across every template family. Baltimore Trips specifically 35 → 99.
  • TTFB: ~800ms → ~30ms globally (Cloudflare edge).
  • Reviews: 4.7 stars across 1,200+ reviews on the main brand, growing.
  • Sister brands: six of them (Baltim, District, Philly, UCW, US Bus, Stretch XL) now serve from the same Hugo stack, no per-site drift.
  • Security incidents: zero WordPress-shaped incidents post-cutover. There is no wp-admin.

What did NOT change: the content. Every page is the same words and largely the same layout it was on WordPress. The migration was a container swap, not a rewrite. This is important - it means the results are attributable to the container, not to new content.

09

The productization - Stretch LLC and Wordpress Escape

The playbook that ran the UC migration is now productized in two places:

  • stretch-llc.com - the operator brand. This is where the transportation-family case studies live and where multi-site enterprise engagements originate.
  • wordpressescape.com - the productized migration service. Single-domain and multi-domain migrations at four tiers: DIY (free playbook), Assisted ($5K-$15K), Managed ($25K-$50K), Enterprise / Family ($100K+/yr retainer).

If you have a WordPress site with an index-bleed problem, a plugin-security problem, or a PageSpeed floor problem - start with the free audit. It runs in 60 seconds, tells you what your real numbers are, and shows exactly what a migration would preserve versus rebuild. Same tool we ran on UC before we quoted the engagement.

10

What we would do differently

Every migration teaches you something. The list, in order of how much time it would have saved us:

  1. Cloudflare email obfuscation off before the CLS test. Would have saved a day of debugging.
  2. Redirect map lookaheads always include the slash form. (?!rental[-/]) not (?!rental-). Two-character fix, hours of loop-debugging saved.
  3. Partition the build from day one. The 11-hour naive build was a rite of passage, but we should have partitioned first and never seen it.
  4. Ship llms.txt in the initial cutover, not as an afterthought. Two months of LLM-search traffic we could have had from day one.
  5. Real-user CrUX watch built into the launch checklist. Staging PageSpeed lies about production for exactly the reason you built the staging site to lie about production - no Cloudflare in front of it.

All five are baked into every subsequent Wordpress Escape migration.

Frequently asked questions

What Hugo version did the UC migration ship on?

Hugo v0.124 extended, running on a standard cPanel VPS with builds triggered via cron. Nothing exotic. The point of choosing Hugo was to keep the toolchain boring.

How much did the WordPress → Hugo migration actually cost in engineering time?

Five engineering days end-to-end for the initial 528,315-page cutover. Ongoing operational burden is roughly one engineer-hour per week for build monitoring and content ops.

What happened to WooCommerce?

WooCommerce was retired. Payment flow was moved to a purpose-built checkout that talks directly to the payment gateway. If your site depends on WooCommerce heavily, migration cost is higher and Managed tier is the right starting point.

Do you have to be Cloudflare to make this work?

No, but you should be. The edge cache is what turns TTFB into a non-issue. Any CDN with edge caching works; Cloudflare's free tier is enough to launch.

Can Wordpress Escape do this for a site smaller than 528K pages?

Yes. Most engagements are 1K-50K pages, Assisted or Managed tier. The 528K case is the proof-point anchor, not the minimum.

What did you use for the WordPress → Hugo content extraction?

Custom extraction scripts against the WordPress database, plus a saturating Screaming Frog crawl to catch anything the DB missed (custom-post-type edge cases, plugin-generated pages, spun long-tail). Both routes were reconciled before any Hugo generation ran.

Scan my site free

See if your site qualifies for the same treatment

The free 60-second audit shows your real PageSpeed score, exact page count, SEO gaps and the WordPress features you need replaced. Then Wordpress Escape rebuilds you on Hugo, keeps every URL, and hands you the source on day one - the same way UC was rebuilt.

Scan my site free
Keep reading
All guides33
Related searcheswordpress to hugo migration528315 pageshugo partitioned buildcloudflare cls fixllms.txt strategystretch llc migration playbookunlimited charters case study