Foreword — Bill
I wanted to write and deploy a blog entirely from my phone while on the train home from NYC. A bit of research turned me on to Cloudflare Workers and I have been totally hypnotized by the speed and elegance of the solve. Even as someone who enjoys standing up the backend bits, shipping from the repo directly makes the whole process so snappy.
The blog covers the technical bits, but I’d encourage anyone trying to just take the Claude context brief and work through it with the agent. You’ll only be expected to do two things (three if you need to install the gh CLI first).
Everything Claude needs: the hosting setup, the deploy pipeline, every gotcha, and a checklist it has to satisfy before it's allowed to tell you it's done. There's one line near the top to fill in — describe your site — and one for your domain.
Show me what I’m copying
# Brief: build and deploy my website to Cloudflare Workers
You are setting up a brand-new static website for me and deploying it to
Cloudflare Workers on a custom domain. Do the whole thing: scaffold, build,
repo, deploy pipeline, first deploy, and verification.
I am not going to hand-edit config files. Ask me questions when you need a
decision, otherwise make sensible choices and tell me what you picked.
---
## What the site is
<<< REPLACE THIS with a few sentences about your site: what it is, what pages
you want, and roughly how it should look. Plain English is fine. If you have a
site you like the look of, name it. >>>
**Domain I want it on:** <<< e.g. jonexample.com or www.jonexample.com >>>
---
## Ground rules
- **Static only.** No server code, no database, no user accounts, no comment
system, no contact form that stores anything. If something I asked for needs
a server, stop and tell me before building a workaround.
- **No secrets in the repo.** Ever. If something needs a key, it goes in GitHub
Actions secrets.
- **No asset over 25 MiB.** Cloudflare rejects the deploy. Check the built
output before deploying and tell me if anything is close.
- **Cheap by default.** Don't add paid services. Don't add a framework I don't
need. Don't add analytics without asking.
---
## Hosting setup
Use **Cloudflare Workers with Static Assets** — not Cloudflare Pages.
Requirements to verify before you start:
- The domain is already an active zone in my Cloudflare account.
- The exact hostname I want has **no existing CNAME record**. A custom domain
cannot attach to a hostname that already has one. If it does, tell me — I
need to delete that record first, and you must not delete it for me.
### wrangler.jsonc
Create it at the repo root, shaped like this:
```jsonc
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "<short-worker-name>",
"compatibility_date": "<today's date, YYYY-MM-DD>",
"assets": {
"directory": "./dist",
"not_found_handling": "404-page"
},
"routes": [{ "pattern": "<my-hostname>", "custom_domain": true }]
}
```
Notes:
- `not_found_handling` must be `"404-page"` for a content site, so unmatched
URLs return a real 404. `"single-page-application"` returns HTTP 200 with
index.html for every wrong URL, which search engines will index. Only use it
if the site is genuinely a client-routed SPA.
- `custom_domain: true` makes Cloudflare create the DNS record and issue the
TLS certificate on the first deploy. I should not have to touch DNS.
- Add `wrangler` as a devDependency. Static Assets need **3.78.10+**; use
current v4.
### Deploy pipeline
GitHub Actions, deploying on push to `main`, plus a manual trigger:
```yaml
name: Deploy
on:
push:
branches: [main]
workflow_dispatch:
concurrency:
group: deploy
cancel-in-progress: false
permissions:
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version-file: .nvmrc
cache: npm
- run: npm ci
- run: npm run build
- uses: cloudflare/wrangler-action@v4
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy
```
Include `workflow_dispatch` so the first deploy can be triggered by hand after
I set the secrets, without needing an empty commit.
Also add a separate CI workflow that build-checks pull requests.
### Secrets
Two repo secrets, which **I** will set — do not ask me to paste the values into
the chat:
- `CLOUDFLARE_API_TOKEN` — created from the **Edit Cloudflare Workers**
template, scoped to my account and my zone.
- `CLOUDFLARE_ACCOUNT_ID` — from the Workers & Pages overview page.
When you're ready for them, give me the exact `gh secret set` commands to run
myself, then wait.
---
## Repo
- Private GitHub repo unless I say otherwise.
- Add a `.gitignore` covering `node_modules/`, build output, `.env`, and
`.wrangler/`.
- Add a `.gitattributes` with `* text=auto eol=lf` so line endings don't churn
between my machine and CI.
- Pin Node in `.nvmrc` and have CI read it with `node-version-file`.
- Write a README that explains how to run it locally, how to add a page or
post, and how deploying works. Assume I'll read it in six months having
forgotten everything.
---
## Definition of done
Don't tell me it's finished until all of these are true, and show me the
evidence for each:
1. `npm run build` succeeds locally with no errors.
2. The dev server (`npm run dev`) starts clean. **Check this separately from
the build** — some failures only appear in one or the other.
3. The deploy workflow run is green.
4. You have fetched the live URL and confirmed HTTP 200.
5. You have confirmed a nonsense URL returns a real **404**, not a 200.
6. **The live page actually renders in a browser.** A 200 from `curl` only
proves bytes came back — a completely blank, broken page returns 200 too. If
you can't open a browser, say so plainly and tell me to check it myself.
7. No file in the build output exceeds 25 MiB.
---
## How to work with me
- I'm not deeply technical. Explain what you're doing in plain language and
skip the jargon, but don't hide problems from me or simplify to the point of
being wrong.
- If something fails, tell me what broke and what you're trying — don't quietly
retry six times.
- If you're about to do something hard to undo (deleting DNS records, force
pushing, deleting files I made), ask first.
- Tell me what things cost before adding them.
Read this part before you start
Four things decide whether this is right for you. They’re all easier to know now than after you’ve built something.
Your site will be static. Every page is a file that’s built ahead of time and handed to visitors as-is. Writing, portfolios, documentation, a band page, a menu, a résumé — all perfect. What it can’t do on its own: user accounts, logins, comments, a search box that queries a database, or a contact form that saves what people submit. Those need a server, and this deliberately has none. That’s the trade that makes the rest of it free and fast.
Your domain has to be on Cloudflare first. Not just bought — actually moved, with its nameservers pointing at Cloudflare and the zone showing active in your dashboard. If you’re not sure, that’s the first thing to ask Claude to check. Most of the convenience below depends on it.
It’s free. Not trial-free. Serving your files costs nothing, there’s no bandwidth bill, and there’s no charge for storing them. The domain is the only thing you pay for. Cloudflare’s free tier has a daily request limit, but it only counts requests that run code — and a static site runs none.
The two tokens
This is the only part nobody can do for you, because they’re credentials to your own account.
You need a Cloudflare API token and your Cloudflare account ID, and they go into GitHub’s secret storage — not into a file, not into the chat. Claude will tell you exactly when it needs them and give you the two commands to run. It’s about two minutes of clicking in the Cloudflare dashboard.
Those commands use gh, GitHub’s command-line tool — that’s the third
thing, and only if you don’t already have it. Claude can walk you through
installing it. Or skip it entirely and paste both values into the repo’s
Settings → Secrets and variables → Actions page in a browser instead; it’s
the same result, just more clicking.
The one thing worth knowing: when you create the token, use the Edit Cloudflare Workers template rather than assembling permissions yourself. The template is already correct.
What actually happens
You paste the brief. You describe your site. Claude scaffolds it, makes a private GitHub repo, writes the deploy pipeline, and stops to ask for those two tokens. You set them. It deploys.
The first deploy is the satisfying bit: Cloudflare creates the DNS record and issues the HTTPS certificate on its own. There’s no step where you copy a cryptic string into a DNS panel and wait. The job goes green and the site is just there, on your domain, with a padlock.
After that, every change you ask for gets pushed and is live in about thirty seconds.
Why bother with Cloudflare specifically
Because your site ends up on the same infrastructure large companies pay for, and the relevant part of it is free.
Your files get copied to data centres worldwide, and visitors are served from whichever one is nearest. This very page came off that network on its way to you — here’s the actual measurement, taken in your browser just now:
- Served from
- …
- Protocol
- …
- Time to first byte
- …
- DOM ready
- …
- Fully loaded
- …
- Transferred
- …
The three-letter code is the airport nearest the data centre that answered you.
When you’ll want a person
Being straight about the edges, because “just ask Claude” isn’t a complete answer:
- You want logins, payments, or a real database. Possible, but it’s a different and much larger project. Say so at the start rather than bolting it on later.
- You care a lot about how it looks. Claude will build you something clean and competent. It will not have taste about your thing. Point at sites you like — that’s worth more than any amount of describing.
- Something breaks in a way you can’t describe. Screenshot it. “It looks wrong” is hard to act on; a picture is not.
Otherwise: copy the brief, paste it, and tell it what you want. That’s the whole job.