Case study · WordPress · 2025

Headless WordPress + Next.js for a Climate SaaS: 47ms TTFB, Editor Kept Gutenberg

Marketing team writes in Gutenberg; the site is static Next.js on Vercel. 47ms TTFB, zero plugin updates pushed to production.

Client
Trovekt
Duration
1.5 month
Team
3 people
Budget
$5-25k
Challenge

What was broken

Trovekt’s marketing site was a Next.js app maintained by their two frontend engineers. Every blog post or pricing-page change opened a JIRA ticket. From the marketing lead’s first draft to live on production, the average was 4 days: PR review, design polish, staging deploy, QA, prod deploy.

Marketing wanted Notion or Webflow. The engineering team didn’t want to give up the build pipeline, image optimization, and Vercel edge caching that kept the site at a 47ms global TTFB.

We were asked for a third option: keep Next.js on the public side, give marketing a real editor, and stop the JIRA queue without anyone changing tools they cared about.

Constraints: no editor on the public domain (security, performance), no rebuild-all on every save (the full Next.js build was 8 minutes), and the marketing CMS had to support the existing content shape — case studies, blog posts, pricing-tier rows, team-member bios. About 140 entries to migrate, mostly out of MDX files and a Notion database.

Solution

What we built

WordPress on a private subdomain (cms.trovekt-internal.com, Cloudflare Access in front of it). Gutenberg as the editor — block editor with our custom blocks matching the existing Next.js component library one-to-one. ACF Pro for structured fields (pricing tiers, team rows, case metrics).

Next.js stayed on Vercel as the public site. We added a small fetch layer using WPGraphQL to pull post data at build time. The interesting piece is the revalidation:

  • WordPress publishes/updates fire a webhook into Vercel’s /api/revalidate endpoint with the changed slug.
  • Next.js uses on-demand ISR to rebuild only that single page (and its /blog index) without touching the other 200+ static pages.
  • A signed payload + HMAC check stops anyone outside the WP install from triggering rebuilds.

Average rebuild time per page: 11 seconds, end-to-end from “Publish” click to live. Image optimization stays in Next.js’ Image component (WP serves originals, Vercel cdn-resizes). Cloudflare Access keeps the WP admin behind SSO so even the URL of the editor is invisible to the public web.

Build time: 6 weeks. Migration of 140 entries written as a one-off Python script that read the existing MDX + Notion exports and POSTed into WP REST with proper ACF shape. The marketing lead validated each migrated page against a screenshot diff before we cut DNS over.

Results

What changed

Time from marketing draft to live: 4 days to 90 seconds. The marketing team writes in Gutenberg, hits Publish, walks to get coffee, and the page is live before they’re back. JIRA tickets for content changes dropped from ~12/week to 0.

Public-site TTFB stayed at 47ms globally (Vercel edge). Lighthouse Performance: 98 desktop / 94 mobile, unchanged from pre-migration. The WPGraphQL layer adds zero runtime cost — it only runs at rebuild.

Frontend engineering hours spent on “please update the pricing page” requests: ~6 hours/week to 0. Marketing stopped Slacking the eng channel. That alone freed ~25 engineer-hours/month for product work.

Numbers that matter

Marketing publish time
-99.97%
4 days → 90 seconds
Per-page rebuild time
-97.7%
8 min (full build) → 11 sec (single page)
Frontend eng hours on content tickets
-100%
~6 hrs/week → 0 hrs/week
Global TTFB
unchanged
47ms → 47ms
Lighthouse Performance (desktop)
unchanged
98 → 98
JIRA content tickets / week
-100%

Tech stack

Built from scratch

  • Custom Gutenberg block library
    Mirrored Trovekt's existing Next.js component library as Gutenberg blocks (hero, feature-grid, pricing-row, customer-logo-strip). Marketing builds pages from the same primitives engineering uses, so the design system stays intact.
  • Vercel on-demand revalidation webhook
    On post save/publish, WordPress fires an HMAC-signed payload to Next.js /api/revalidate with the changed slug. Single-page rebuild on average 11s, no global redeploy.
  • Cloudflare Access + WP admin lockdown
    WP install lives on a private subdomain behind Cloudflare Access SSO. Public side never sees WP-Admin, wp-login.php, or any plugin URL. Reduces attack surface to near zero.
  • WPGraphQL schema map
    Curated WPGraphQL schema exposes only the fields Next.js consumes — no kitchen-sink graph traversal. Documented per-page query alongside each Next.js page component for review-ability.

Third-party integrations

  • Vercel (Next.js hosting) — Edge static delivery for the public site. On-demand ISR for per-page rebuilds. No change from pre-migration setup.
  • WPGraphQL — GraphQL layer over WordPress data. Used at build/revalidate time only — public site never queries WP at runtime.
  • Cloudflare Access — SSO gate in front of cms.trovekt-internal.com. The WordPress URL is invisible to the public internet.
  • Cloudflare R2 — Image storage that Vercel reads through its Image component. WP uploads land in R2 via a small plugin, off the WordPress host filesystem entirely.

I write in Gutenberg, which is fine. Then I hit publish and the page is live. That used to be a JIRA ticket and four days. Our engineers stopped getting Slacked about typos.

David A. , Head of Marketing, Trovekt

Similar cases

Want headless WordPress without the rebuild-time tax?

Send us a brief — we'll respond within 24 hours.

Contact Form Demo