Skip to content

Architecture Decision

When the Platform Could Not Carry the Product: Moving to Headless WordPress with Next.js

Close to launch, a large-scale US civic information platform's client brought behaviors plain WordPress could not run: an address-based sample ballot live from the Google Civic API, an interactive polling-place map, and a 700+ candidate directory with real-time filters. I told the client directly the platform could not carry it, negotiated $1,000 and one more month, and split the architecture: WordPress for content and commerce, Next.js for everything interactive. The platform launched, and the client is now building mobile and iOS apps on it.

HighPublished

At a glance

A large-scale US civic information platform's WordPress build could not support the interactive, data-driven features the client brought just before launch.

  • Told the client directly that the current platform could not carry the new requirements
  • Negotiated $1,000 in additional budget and one more month
  • Split the architecture: WordPress for content and commerce, Next.js for the interactive frontend
Result

The platform launched successfully. The client is now building mobile and iOS apps on the same platform, and extending it to more election types.

The situation

A large-scale US civic information platform was being built in WordPress. Close to launch, the client brought behaviors plain WordPress does not do: an address-based sample ballot pulling a voter's own races and candidates live from the Google Civic Information API, an interactive map for polling places and drop-off locations, and a 700+ profile candidate directory with real-time filters and a comparison tool. On top of that sat a candidate self-service portal and a tiered Verified Candidate Program running on recurring subscriptions.

How it surfaced

The gap was not effort, it was platform. WordPress handles content and standard functionality well, but stateful, real-time behavior across 700+ records turns into a maintenance liability of custom plugins bolted onto a system never built for them. Recognizing that early was the actual decision point.

What I ruled out, and why

I ruled out WordPress plugins: more custom work than a proper rebuild, and harder to maintain afterward. The sample ballot and filtered directory needed a real data layer for live third-party integrations (address parsing, caching, graceful fallback), and hundreds of SEO-critical candidate pages needed performance a theme does not deliver at that scale. The strongest reason was growth: an API-first backend means a new election tier later, or a future mobile app, is not a re-platform. Splitting the frontend from a platform holding voter and donation data also shrinks the attack surface: an election-day spike hits the CDN, not the backend holding admin access and payments.

The decision and what it cost

I went to the client directly: the platform could not carry this without more budget and time. They agreed to $1,000 and one more month. I kept WordPress for what it was already good at: JetEngine already handled 700+ structured records the team knew how to run, and WooCommerce Subscriptions already handled the tiered plans and donations the Verified Candidate Program needed.

What I did

The split was deliberate. WordPress kept the content, admin tooling, and commerce: JetEngine for records, WooCommerce Subscriptions for billing. Next.js took the sample ballot, the map, the filtered directory, the comparison tool, and the self-service portal: everything that needed to be fast, interactive, and indexable. A custom REST bridge connects the two.

The outcome

The platform launched successfully on the split architecture. The client is now building mobile and iOS apps on the same platform, and extending it to state, county, municipal, school-board, and judicial elections without a re-platform. Near the end of the project, the client put it plainly: "it's not just a website, it's a platform of ultimate solutions."

What stayed changed

Telling a client their current platform cannot carry what they are asking for, and asking for the budget that carrying it properly requires, is not a conversation to avoid: it is the conversation that gets a client who trusts the answer. Headless did not mean discarding WordPress, it meant giving each half of the stack only the job it is actually good at.

Related incidents