Lesson 5 of 6
Choose Cloudflare Workers or Pages
Pick Workers with static assets or Pages from current official behaviour, write a decision note, and preview locally on the matching port — without deploying yet.
The honest current picture
Cloudflare has two overlapping hosts. Pages is a static-asset host with optional Pages Functions. Existing Pages projects keep working. Workers is a compute platform that can also serve static assets from the same deploy. Current docs present Workers as the way to ship full-stack apps, and a Pages→Workers migration guide exists because newer features land on Workers first.
Two facts from that guide: static-asset requests are free on both, and Pages Functions invocations are charged like Workers — check current pricing yourself; this course does not promise a free tier. Workers has the broader set: Durable Objects, Cron Triggers, Workers Logs, gradual deployments. Neither is wrong. Pick the one whose behaviour you can explain.
The ordering difference that bites
| Behaviour | Pages | Workers static assets |
|---|---|---|
| Files | upload / build output dir | assets.directory in Wrangler config |
| Missing routes | auto from index.html / 404.html |
explicit not_found_handling |
| Request order | Functions run ahead of assets | assets run ahead of the Worker unless run_worker_first |
| Local preview | npx wrangler pages dev <dir> default 8788 |
npx wrangler dev default 8787 |
| Deploy | npx wrangler pages deploy <dir> --project-name <name> |
npx wrangler deploy |
| Custom domain whose nameservers are not on Cloudflare | supported (CNAME) | not supported |
This tracker is one index.html, no client routing, no server code, so ordering does not matter yet. It matters the moment you add /api/*. File-based functions/ routing is first-class on Pages (functions/api/health.js → /api/health). Workers has no equivalent folder; you write a main script.
Decision table and Workers config for this app
New static app, maybe a small API later → Workers with static assets. Existing Pages project with a URL you cannot break → stay on Pages. Nameservers outside Cloudflare → Pages. Cron, Durable Objects, Workers Logs → Workers. Drag a folder in the dashboard → Pages upload is shortest.
For a brand-new tracker, choose Workers. Create wrangler.jsonc next to public/ (not inside it). Set compatibility_date to the date you create the file (example 2026-09-13). $schema is optional editor help and only resolves if Wrangler is installed locally (npm install -D wrangler); npx wrangler works without that.
{
"name": "task-tracker-yourname",
"compatibility_date": "2026-09-13",
"assets": {
"directory": "./public"
}
}
name is lowercase and unique. assets.directory must be the folder that contains index.html. Omit main — no Worker script yet. You do not need not_found_handling for this one-page app. Do not put secrets in vars; those are plaintext.
Write the decision and preview locally
Create a Cloudflare account at dash.cloudflare.com and verify email if you have not. Then:
npx wrangler login
npx wrangler whoami
If the browser cannot reach localhost for the OAuth callback, use npx wrangler login --device.
Workers preview (port 8787):
cd ~/projects/task-tracker
npx wrangler dev
Pages preview (port 8788) if you chose Pages — no config file required for a static-only project:
npx wrangler pages dev ./public
Confirm the tracker loads and that you did not upload the repo root (that would publish notes and config). Write DECISION.md: target; two reasons tied to ordering, routing, domains, or the matrix; one capability you are giving up.