Skip to main content
Case Study

GameHaunt

Migrating a 13-year-old gaming publication from a monolithic WordPress site to a headless architecture. Astro SSR on the frontend, WordPress as the content backend, zero broken URLs, and a custom ad system that survived the transition.

GameHaunt gaming publication
Astro 6.3TypeScriptWordPressWPGraphQLTailwind CSS v4SupabaseNginxPM2GitHub ActionsNode.js SSRSelf-Hosted UbuntuLet's Encrypt SSL

The Problem

GameHaunt had been publishing gaming news, reviews, and pop culture coverage since 2012. It ran on Zeen, a WordPress theme that had accumulated deep technical debt. Page loads were slow. The theme was difficult to modify. The frontend and backend were so tightly coupled that even small design changes meant touching PHP templates that had not been updated in years.

But a site that has been online for 13 years has backlinks, search rankings, direct readers, and an ad system that pays the bills. You cannot just rebuild it. The brief was clear: keep WordPress as the content backend, replace everything the public sees, and do not break a single URL.

The Solution

A headless WordPress architecture with an Astro SSR frontend. Editors continue publishing in the WordPress admin exactly as they always have. WPGraphQL exposes that content through a GraphQL API. The Astro frontend fetches it at request time, renders it server-side, and serves the page through Nginx. Neither side knows the other exists.

  • 1.Resilient data fetching — every WPGraphQL call uses a 10-second timeout with AbortController and the takeWithFallback() pattern. A static dataset of 31 articles kicks in when WordPress is unreachable, so the homepage always renders.
  • 2.13 years of SEO preserved — custom 301 redirects in Astro middleware map every legacy WordPress category URL to the new clean path structure. Search engine link equity transfers without loss.
  • 3.Ad system migration — 13 placement slots mapped to standard IAB sizes with mid-content injection. Custom tracking logs impressions, viewability via IntersectionObserver, and clicks to Supabase, with 25+ bot user-agent patterns filtered out.
  • 4.HTML sanitization as a security boundary — every article body passes through sanitize-html before reaching the page. Iframes restricted to YouTube, Vimeo, and Twitch. All external links get rel="noopener noreferrer" applied automatically.
  • 5.Self-hosted CI/CD — GitHub Actions runs type-check and build on every PR, then rsyncs to the Ubuntu VM on push to main. PM2 performs zero-downtime reloads. No platform lock-in.

Results

13
Years of SEO equity preserved
13
Ad placement slots migrated
0
Broken URLs during cutover

Architecture Highlights

The stack is deliberately simple. A single Node.js process runs the Astro SSR server on port 3000, managed by PM2. Nginx sits in front for TLS termination and reverse proxy. No Docker, no containers, no serverless functions. For a site of this scale, that simplicity is a feature.

The data flow is clean: WordPress (wp.gamehaunt.com) → WPGraphQL → Astro SSR (Node.js) → Nginx → Visitor. Editors never touch the Astro codebase. Readers get a fast, modern site. Security headers (X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy) are set on every response via Astro middleware.

The responsive image pipeline builds srcset attributes from WordPress thumbnail sizes rather than relying on an on-the-fly resizing service. A CDN at assets.gamehaunt.com serves static files. TypeScript strict mode enforces type safety across all library modules.

Read the full migration deep dive

The detailed post covers the fallback pattern, legacy URL preservation, ad system architecture, HTML sanitization strategy, and CI/CD design.

Read the architecture deep dive

Planning a CMS migration or headless architecture? Get in touch to discuss migration strategy, URL preservation, and the tradeoffs of decoupled architectures.