Deploying to Cloudflare Pages
A structured walkthrough for shipping static sites with Wrangler CLI, branch deploys, and zero-downtime rollbacks.
This is the runbook I wish existed when I set up korfe.org. Cloudflare Pages is excellent infrastructure, but the docs assume you already know how the pieces fit together. This walkthrough does not.
Prerequisites
- A Cloudflare account with a zone (domain) attached
- Wrangler CLI installed:
npm install -g wrangler - An API token with Cloudflare Pages: Edit permissions
Store your token in a .env file at your project root:
CF_API_TOKEN=your_token_here
Project structure
Cloudflare Pages expects a dist/ output directory and an optional functions/ directory for serverless functions. Critical: Wrangler resolves functions/ relative to your current working directory, not relative to dist/. Always run deploy commands from the directory that contains functions/.
your-project/
site/
dist/ ← build output
functions/ ← serverless functions
package.json
Build and deploy
cd your-project/site
# Build
npm run build
# Deploy to preview
CLOUDFLARE_API_TOKEN=$CF_API_TOKEN npx wrangler pages deploy dist \
--project-name your-project-name
# Deploy to production
CLOUDFLARE_API_TOKEN=$CF_API_TOKEN npx wrangler pages deploy dist \
--project-name your-project-name \
--branch=main
The --branch=main flag is what triggers a production deployment. Without it, every deploy goes to a unique preview URL.
Branch deploys
Every deploy without --branch=main creates a preview URL at a subdomain of your Pages project. You can also set up a persistent alias:
In the Cloudflare dashboard, go to Pages → your project → Custom domains and add dev.yourdomain.com pointing to your preview branch.
Environment variables
Set secrets in the Cloudflare dashboard under Pages → Settings → Environment variables. These are available at runtime in functions/ via context.env.YOUR_VAR.
Do not commit secrets to your repo. Do not put them in wrangler.toml.
Rollbacks
Every Cloudflare Pages deployment is retained and can be re-activated instantly from the dashboard. If a production deploy breaks something:
- Go to Pages → your project → Deployments
- Find the last known-good deployment
- Click Retry deployment (this re-promotes it to production)
This is zero-downtime. The old deployment stays live until the re-promotion completes.
Common gotcha: working directory
If your functions aren’t running in production but your static pages are, the likely cause is deploying from the wrong directory. Wrangler uploads functions/ from wherever you run the command — if it doesn’t find a functions/ folder there, it silently skips it.
Always cd into the directory that contains both dist/ and functions/ before deploying.