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
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
Managing Scope Creep with Clients: A Single-Vendor Platform Becomes Multi-Vendor Mid-Build
A client changed an education platform from single-vendor to multi-vendor mid-build: a structural change, not a feature request. As Associate Project Manager, I asked for more time; the client declined but increased the budget instead. I split the added work so the developers already on the project handled what needed context, and new developers handled what did not. The original delivery held, and Phase 2 shipped after it.
- Multi-Vendor Pivot
- Budget Negotiation
- Work Splitting
A Launch Delayed an Hour by an Undisclosed Implementation Choice
Ahead of a SaaS launch for an international client, I asked a developer to build one API route pulling the admin dashboard's data from multiple tables at once. He built several separate calls on the same page instead, and didn't tell me. I fixed the query layer myself with indexing and a rewritten query, and told the client the launch would be about an hour late, rather than let a slow admin page surface on its own.
- SQL Indexing
- Query Rewrite
- Undisclosed Change