Cloudflare Pages
Full-stack application hosting with Git-based or Direct Upload deployments to Cloudflare's global network.
Quick Navigation
- Deployment methods →
references/deployment.md - Build configuration →
references/build.md - Pages Functions →
references/functions.md - Bindings →
references/bindings.md - Headers & Redirects →
references/headers-redirects.md - Custom domains →
references/domains.md - Wrangler CLI →
references/wrangler.md
When to Use
- Deploying static sites or JAMstack applications
- Building full-stack apps with serverless functions
- Configuring Git-based CI/CD deployments
- Using Direct Upload for prebuilt assets
- Setting up preview deployments for branches/PRs
- Configuring custom domains and redirects
Deployment Methods
| Method | Best For | Limits | | --------------- | ----------------------------- | ------------------------------------ | | Git integration | CI/CD from GitHub/GitLab | Cannot switch to Direct Upload later | | Direct Upload | Prebuilt assets, CI pipelines | Wrangler: 20k files, 25 MiB/file | | C3 CLI | New project scaffolding | Framework-dependent |
Quick Deploy
# Create project
npx wrangler pages project create my-project
# Deploy
npx wrangler pages deploy ./dist
# Preview deployment (branch)
npx wrangler pages deploy ./dist --branch=feature-x
Build Configuration
# Framework presets (command → output directory)
# React (Vite): npm run build → dist
# Next.js: npx @cloudflare/next-on-pages@1 → .vercel/output/static
# Nuxt.js: npm run build → dist
# Astro: npm run build → dist
# SvelteKit: npm run build → .svelte-kit/cloudflare
# Hugo: hugo → public
Environment Variables (build-time)
| Variable | Value |
| --------------------- | -------------- |
| CF_PAGES | 1 |
| CF_PAGES_BRANCH | Branch name |
| CF_PAGES_COMMIT_SHA | Commit SHA |
| CF_PAGES_URL | Deployment URL |
Pages Functions
File-based routing in /functions directory:
/functions/index.js → example.com/
/functions/api/users.js → example.com/api/users
/functions/users/[id].js → example.com/users/:id
// functions/api/hello.js
export function onRequest(context) {
return new Response("Hello from Pages Function!");
}
Handler Types
| Export | Trigger |
| --------------- | ----------- |
| onRequest | All methods |
| onRequestGet | GET only |
| onRequestPost | POST only |
Context Object
interface EventContext {
request: Request;
env: Env; // Bindings
params: Params; // Route parameters
waitUntil(promise: Promise<any>): void;
next(): Promise<Response>;
data: Record<string, any>;
}
Bindings
Access Cloudflare resources via context.env:
| Binding | Access Pattern |
| ---------- | ---------------------------------------- |
| KV | context.env.MY_KV.get("key") |
| R2 | context.env.MY_BUCKET.get("file") |
| D1 | context.env.MY_DB.prepare("...").all() |
| Workers AI | context.env.AI.run(model, input) |
For detailed binding configuration, see:
cloudflare-workersskill.
Headers & Redirects
Create _headers and _redirects in build output directory.
# _headers
/*
X-Frame-Options: DENY
/static/*
Cache-Control: public, max-age=31536000, immutable
# _redirects
/old-page /new-page 301
/blog/* https://blog.example.com/:splat
Warning:
_headersand_redirectsdo NOT apply to Pages Functions responses.
Functions Invocation Routes
Control when Functions are invoked with _routes.json:
{
"version": 1,
"include": ["/api/*"],
"exclude": ["/static/*"]
}
Wrangler Configuration
// wrangler.jsonc
{
"name": "my-pages-app",
"pages_build_output_dir": "./dist",
"compatibility_date": "2024-01-01",
"kv_namespaces": [{ "binding": "KV", "id": "<NAMESPACE_ID>" }],
"d1_databases": [{ "binding": "DB", "database_name": "my-db", "database_id": "<ID>" }]
}
Local Development
npx wrangler pages dev ./dist
# With bindings
npx wrangler pages dev ./dist --kv=MY_KV --d1=MY_DB=<ID>
Critical Prohibitions
- Do NOT expect
_headers/_redirectsto apply to Pages Functions responses — attach headers in code - Do NOT convert Direct Upload project to Git integration — not supported
- Do NOT exceed redirect limits — 2,000 static + 100 dynamic redirects max
- Do NOT use absolute URLs for proxying in
_redirects— relative URLs only - Do NOT edit bindings in dashboard when using Wrangler config — file is source of truth
- Do NOT store secrets in
wrangler.toml— use dashboard or.dev.varsfor local
Common Gotchas
| Issue | Solution |
| ---------------------- | ----------------------------------------------------- |
| Functions not invoked | Check _routes.json include/exclude patterns |
| Headers not applied | Ensure not a Functions response; attach in code |
| Build fails | Check build command exit code (must be 0) |
| Custom domain inactive | Verify DNS CNAME points to <site>.pages.dev |
| Preview URLs indexed | Default X-Robots-Tag: noindex applied automatically |
Quick Recipes
Conditional Build Command
#!/bin/bash
if [ "$CF_PAGES_BRANCH" == "production" ]; then
npm run build:prod
else
npm run build:dev
fi
SPA Fallback (404.html)
Upload 404.html in build output root for SPA routing.
Disable Functions for Static Assets
// _routes.json
{
"version": 1,
"include": ["/api/*"],
"exclude": ["/*"]
}
Links
Related Skills
cloudflare-workers— Worker runtime, bindings API detailscloudflare-d1— D1 SQL database operationscloudflare-r2— R2 object storagecloudflare-kv— KV namespace operations