WordPress to static site migration: a case study covering the GitHub and Cloudflare Workers publishing pipeline, the Claude Code editing setup for three contributors, and the domain cutover ETTE delivered for Results One LLC, a DEIA and disability services consulting firm.
Off WordPress and onto a site the client owns, in one month
Results One LLC is a DEIA and disability services consulting firm led by its two co-founders. In late July 2026 the firm engaged ETTE to move resultsonellc.com off WordPress on WP Engine hosting and onto static HTML, CSS, and JavaScript managed through GitHub, Cloudflare Workers, and Claude Code. The engagement closed on August 31, 2026, with the new site live on the production domain and three people at the firm editing it on their own branches. Every date and count comes from the project record.
From WP Engine hosting to a repository and Worker the client owns
ETTE opened the accounts under the client's own name first, built a publishing pipeline that keeps production and preview apart, and only then connected editors and moved content. The domain moved last, after a full DNS snapshot.
-
Accounts in the client's nameA GitHub account and a free Cloudflare account created under Results One's name. The client owns both, as the statement of work required.
-
Repository safeguardsAn
.assetsignorefile and a committedwrangler.jsoncin the first commit, before the first deploy -
Publishing pipelineThe main branch deploys to production at 100 percent traffic; every other branch uploads a version to its own preview URL at zero percent
-
Editors connectedEach contributor's Claude Code cloud session bound to their own branch, with network access opened to the old site for reference content
-
Content, then domain37 pages transcribed; DNS snapshotted; nameservers moved to Cloudflare; both hostnames verified live against the domain itself
Three editors, one production branch, no overwritten work
The statement of work named one client contact. By the end of the engagement three people were editing the site. The branch and access model was built for that kind of growth: each contributor works on a dedicated branch off main, and nothing reaches production until it has been reviewed and merged.
A branch and Write access per contributor
Two collaborators were added over the course of the project with Write access rather than Admin, enough for content work through Claude Code without repository administration rights. On a personal GitHub account only the repository owner can send collaborator invitations, whatever anyone else's permission level, so every invitation went out from the client's own account. That is a GitHub platform constraint, not a permissions setting.
Claude Code bound to each branch
Every contributor set up the same way in the Claude Desktop app's Code tab: a new session with the environment set to Cloud, GitHub authorized under their own login against the client's existing Claude GitHub App installation, the repository selected, and the branch set explicitly to their own, not the default main. Network access was set to Custom and opened to the client's domains, plus the WordPress CDN and Google Fonts hosts during transcription.
A preview URL per branch
The non-production deploy command was first set to a single hardcoded alias, which would have sent every contributor's branch to the same preview URL. ETTE changed the Workers Builds command to read the branch name from Cloudflare's own injected variable: npx wrangler versions upload --preview-alias $WORKERS_CI_BRANCH. Every branch, including one added in the project's last days, gets a distinct, stable preview with no per-contributor configuration.
A weekend merge freeze before the review
Ahead of the final meeting, both client contributors worked on their own branches over a weekend with no ETTE availability. Neither merged to main until both sets of changes had been reviewed together on August 31. One merge conflict came out of that weekend. It was resolved by reading both versions and hand-merging the intent of each edit rather than picking a side.
Project timeline
.assetsignore and wrangler.jsonc committed before the first deploy; Worker-versus-Pages preview behavior confirmed before the live sessionSeven things that broke or nearly broke, and the fix for each
Two of these were caught before the first deploy. The rest surfaced during onboarding and cutover and were fixed the same day. Each is recorded here because the next migration of this kind will meet the same ones.
Wrangler uploads everything in the assets directory unless told otherwise, and that includes a repository's .git folder. ETTE added an .assetsignore file listing .git and .wrangler at the repository root before the first deploy, instead of catching it in review afterward.
Cloudflare's Connect-to-Git flow generates wrangler.jsonc during the first interactive deploy and, in that flow, adds it to .gitignore by default. Left uncommitted, every build on a non-production branch fails with a missing entry-point error. A working wrangler.jsonc was committed from the very first commit.
With the non-production command set to --preview-alias dev, each new branch would have overwritten the same preview. Reading the alias from $WORKERS_CI_BRANCH, a variable Workers Builds injects on every build, gives each branch its own address without touching Cloudflare again.
Fetching reference content from resultsonellc.com produced an EGRESS_BLOCKED error the first time a contributor tried. Each cloud session was set to Custom network access allowing the client's two hostnames and, during transcription, the WordPress image CDN and the Google Fonts hosts.
One contributor's push failed because the Cloudflare Workers and Pages app, which manages the git-to-deploy connection, had been conflated with the Claude app, which grants Claude Code's cloud sessions read and write access to the repository. Reconnecting GitHub from the Claude.ai Settings, Connectors page cleared it.
A live RDAP lookup against the .com registry identified the registrar as Squarespace Domains II LLC, not the GoDaddy or Wix accounts first suspected. Google sold its Google Domains business to Squarespace in 2023 and migrated every account automatically. This domain, registered in 2017, had moved with it, and the account belonged to a different contact at the firm than assumed.
Cloudflare's dashboard failed to recognize www.resultsonellc.com as part of the already-active zone when adding it as a Custom Domain. ETTE added it through wrangler.jsonc instead, as a routes entry with custom_domain set to true, which Workers Builds picks up on its own. The apex Custom Domain entry also disappeared partway through the cutover and was re-added once the zone was confirmed active.
Email kept working through the nameserver change
Results One runs its mail on Google Workspace, and third-party services authenticate against the domain. Before any change, ETTE took a full live DNS snapshot, reproduced every record in the client's new Cloudflare zone, and re-verified each one live after the client updated the nameservers to the pair Cloudflare assigned.
| Type | Host | Purpose |
|---|---|---|
| MX (5 records) | @ (apex) | Google Workspace mail routing, priorities 10 to 50 |
| TXT | @ (apex) | Google Workspace domain verification |
| TXT | @ (apex) | Legacy Microsoft domain verification |
| CNAME | s1._domainkey, s2._domainkey | Third-party DKIM signing (SendGrid-pattern selectors), preserved as CNAMEs exactly as Cloudflare imported them |
Final verification went against the live domain, not the dashboard. resultsonellc.com returned a clean HTTP 200 from the new static site. www.resultsonellc.com returned a Cloudflare-native 301 redirect to the apex. Neither response carried any trace of WP Engine.
What shipped by August 31
Fully migrated from WordPress and live on resultsonellc.com and www.resultsonellc.com, with every image stored in the repository instead of hotlinked from the old CDN.
Each contributor edits through Claude Code on their own branch with their own preview URL. The prompts used for ongoing edits carry a WCAG 2.1 Level AA confirmation step before any change and a branch-safety confirmation before any commit.
The contact and consultation forms submit through Formspree: a form endpoint pasted into the site's existing JavaScript, spam filtering included, 50 submissions a month free and a $10-a-month Personal tier at 200 a month, billed annually, if the firm outgrows it. The client tested the integration before it went live.
A late addition for a newly onboarded contributor: hosted checkout links on the eBook pages, embeddable as a buy button, instead of a cart and inventory system for a handful of individual products.
No lost MX, DKIM, or verification records. The registrar was located by RDAP lookup and the nameservers changed by the client from an account only they control.
The GitHub repository, the Cloudflare account, and the domain all belong to Results One. The statement of work excluded ongoing maintenance, and the handoff left nothing that needs ETTE to keep running.
Who did what
A small group on both sides. The client held every account and sent every invitation; ETTE built the pipeline and handled the parts that go wrong.
Built the publishing pipeline and its safeguards, confirmed the Worker-versus-Pages preview behavior before the live session, onboarded each contributor's Claude Code session, ran the RDAP lookup and the DNS snapshot, and handled the same-day fixes during the domain cutover.
Created the GitHub and Cloudflare accounts under the firm's name, owns the repository, and sent every collaborator invitation, since only the owner of a personal GitHub account can. Tested the Formspree integration before it took real submissions.
Added with Write access over the course of the project, each on a dedicated branch and a Claude Code cloud session. One joined in the project's last days and brought the eBook payment-link request. Both edited over the final weekend under the merge freeze.
A different contact at the firm than first assumed held the Squarespace account, most likely from handling renewals over the years. They updated the domain's nameservers to the pair Cloudflare assigned to the new zone.
What ETTE will do first on the next migration like this
Cloudflare's Connect-to-Git flow can provision either. They differ on custom preview subdomains, and a preview link on a workers.dev address is a surprise to a client expecting one on their own domain.
Before the first real deploy, not after. Together they prevent a published .git directory and a missing entry-point failure on every non-production build.
Use --preview-alias $WORKERS_CI_BRANCH on any project that expects more than one contributor, even if only one is named in the statement of work.
Long-registered domains are frequently sitting somewhere the client does not remember, most often a Google Domains account that became a Squarespace account in 2023. A live RDAP or WHOIS lookup settles it in a minute.
Capture every record, especially MX, TXT, and DKIM, before any nameserver change, and re-check against the live domain afterward. The dashboard alone is not proof.
If your site is on WordPress and more than one person needs to edit it
Static sites for firms that want to own their web presence
Consulting firms and nonprofits on WordPress pay for hosting, plugins, and updates, and still depend on whoever holds the admin login. This engagement moved a 37-page site to plain HTML in a repository the client owns, on a free Cloudflare account, with a pipeline that lets three people edit safely through Claude Code and a preview URL for every change before it goes live.
ETTE scopes this work as a defined statement of work: accounts in your name, the pipeline and its safeguards, and a live session on the edit, preview, publish loop. Content, design, and domain fees stay with you, and so does everything ETTE builds. For how the same accessibility standard was applied to a nonprofit's site, see the website accessibility case study.