Building a 1-Click Site Platform: From SSL Nightmares to Production Success
What a day! Just shipped BadBoothSites — a complete 1-click site platform that can provision, migrate, and deploy WordPress sites at the push of a button.
The Big Win
Got gethoneybun.com fully live with proper SSL, domain mapping, and all the bells and whistles. The whole stack is now working end-to-end:
- R2 bucket storing themes (2.5MB gethoneybun-theme uploaded)
- Cloudflare Worker handling all the orchestration
- WordPress sites that can be migrated, themed, and taken live automatically
Built out 6 core operations that work together like clockwork:
- Provision — Spin up new sites from a golden template
- Deploy Theme — Push themes from R2 storage
- Migrate — Import content from existing WordPress sites
- Go Live — 1-click domain cutover with SSL
- SSL Fix — Troubleshoot and repair SSL issues
- Cloudways Ops — Server management reference
The SSL Horror Story
Hit a nasty Cloudflare 526 error that had me scratching my head for way too long. Turns out when you have custom domains on the same Cloudflare account, Worker→WordPress calls get confused and throw SSL errors.
The fix? Always use staging URLs for internal API calls. Built a wpFetch() helper that handles the 526 fallback automatically. Sometimes the simple solutions are the best ones.
Another gotcha: Let's Encrypt kept replacing my wildcard certs. Solution was to include the staging URL in the Subject Alternative Names so everything plays nice together.
End-to-End Testing
Ran the full flow and it's beautiful:
- ✅ R2 Asset List
- ✅ Deploy Theme from R2
- ✅ Migrate Site (imported 4 pages from wordpress.org)
- ✅ Go Live (6/7 steps passing)
That last failing step is just missing one mu-plugin install — easy fix for next session.
The Technical Bits
Had to work around some SCP permission issues with a /tmp workaround since the master user can't write directly to app-user directories. Classic server permissions dance.
Also learned that route ordering matters — /go-live/bare was getting matched as /go-live/:clientId with "bare" as the client ID. Moved the specific route above the parameterized one and boom, fixed.
What's Next
The platform is basically done and deployed. Just need to:
- Install the final mu-plugin for the last go-live step
- Test the provision flow end-to-end
- Store staging URLs in the dashboard for automatic routing
Feels good to have a clean slate going into the next session. Sometimes you just need to push through and ship the thing. 🚀