
Cloudflare Pages
- 79 installs
- 44 repo stars
- Updated May 22, 2026
- bagelhole/devops-security-agent-skills
cloudflare-pages is a Claude Code skill that deploys static sites and full-stack apps on Cloudflare Pages with previews, Pages Functions, and custom domains.
About
This skill deploys static sites and full-stack apps on Cloudflare Pages. It covers Wrangler CLI project setup, Git integration, automatic per-PR preview deployments, Pages Functions with KV/D1/R2 bindings, custom headers, and redirects. A developer uses it when deploying a frontend or full-stack project to Cloudflare's edge with previews and custom domains. It matters for shipping sites with zero-config CDN and TLS.
- Deploys static sites and full-stack apps on Cloudflare Pages
- Covers preview deployments, Pages Functions, and KV/D1/R2 bindings
- Uses Wrangler CLI, Git integration, and framework build presets
Cloudflare Pages by the numbers
- 79 all-time installs (skills.sh)
- Ranked #624 of 1,039 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Data as of Jul 28, 2026 (Skillselion catalog sync)
cloudflare-pages capabilities & compatibility
Free Cloudflare tier works for most projects; needs wrangler login or CLOUDFLARE_API_TOKEN
- Capabilities
- cloudflare workers · cloudflare r2 · cdn setup
- Works with
- cloudflare · github · gitlab
- Use cases
- devops · frontend
- Platforms
- macOS · Linux · Windows
- Pricing
- Freemium
What cloudflare-pages says it does
Deploy frontend projects with preview builds, edge functions, and global CDN delivery on Cloudflare's network.
Migrating from Vercel, Netlify, or GitHub Pages to Cloudflare's ecosystem.
npx skills add https://github.com/bagelhole/devops-security-agent-skills --skill cloudflare-pagesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 79 |
|---|---|
| repo stars | ★ 44 |
| Last updated | May 22, 2026 |
| Repository | bagelhole/devops-security-agent-skills ↗ |
What it does
Deploy static sites and full-stack apps to Cloudflare Pages with preview builds, functions, and custom domains.
Who is it for?
Deploying static or full-stack frontend projects to Cloudflare's edge with previews and custom domains
Skip if: Long-running backend servers or non-edge compute workloads
When should I use this skill?
Deploying static sites or full-stack apps to Cloudflare Pages, or wiring up Pages Functions and previews
What you get
A site deployed on Cloudflare Pages with preview URLs, edge functions, and a custom domain.
- Deployed Pages project
- Preview deployment URLs
- Pages Functions with bindings
By the numbers
- Framework preset table covers 6 frameworks (React CRA, Vite, Next.js, Astro, Hugo, SvelteKit)
Files
Cloudflare Pages
Deploy frontend projects with preview builds, edge functions, and global CDN delivery on Cloudflare's network.
When to Use
- Deploying static sites (React, Vue, Astro, Hugo, Next.js static export).
- Full-stack applications using Pages Functions for server-side logic.
- Projects that need automatic preview deployments per pull request.
- Teams that want zero-config CDN with custom domain and TLS.
- Migrating from Vercel, Netlify, or GitHub Pages to Cloudflare's ecosystem.
Prerequisites
- Node.js 18+ and npm installed locally.
- A Cloudflare account (free tier works for most projects).
- Wrangler CLI installed:
npm install -g wrangler. - Authenticated via
wrangler loginorCLOUDFLARE_API_TOKENenvironment variable. - Source code in a Git repository (GitHub or GitLab for dashboard integration).
Project Setup via Wrangler
Create a New Project
# Create a new Pages project
npx wrangler pages project create my-site
# List existing projects
npx wrangler pages project list
# Delete a project (removes all deployments)
npx wrangler pages project delete my-siteDeploy from Local Build Output
# Build your framework first
npm run build
# Deploy the output directory
npx wrangler pages deploy dist --project-name=my-site
# Deploy with a custom branch name (triggers preview URL)
npx wrangler pages deploy dist --project-name=my-site --branch=feature-auth
# Deploy and get the deployment URL in JSON
npx wrangler pages deploy dist --project-name=my-site --branch=main 2>&1 | tail -1List and Manage Deployments
# List recent deployments
npx wrangler pages deployment list --project-name=my-site
# Tail live logs from a deployment
npx wrangler pages deployment tail --project-name=my-site --environment=productionDashboard Git Integration
1. Navigate to Workers & Pages > Create application > Pages. 2. Connect your GitHub or GitLab account. 3. Select the repository and configure:
- Production branch:
main - Build command:
npm run build - Build output directory:
dist(orbuild,.next,publicdepending on framework)
4. Set environment variables per environment (Production vs Preview).
Framework Presets
Cloudflare auto-detects frameworks. Override if needed:
| Framework | Build Command | Output Directory |
|---|---|---|
| React CRA | npm run build | build |
| Vite | npm run build | dist |
| Next.js | npx @cloudflare/next-on-pages | .vercel/output/static |
| Astro | npm run build | dist |
| Hugo | hugo | public |
| SvelteKit | npm run build | .svelte-kit/cloudflare |
Preview Deployments
Every non-production branch gets a unique preview URL automatically.
# URL format for preview deployments
https://<commit-hash>.<project-name>.pages.dev
https://<branch-name>.<project-name>.pages.devBranch-Based Access Control
# Set preview branch patterns in wrangler.toml (Pages-specific)
# Or configure via dashboard: Settings > Builds & deployments
# Include branches: feature/*, staging
# Exclude branches: dependabot/*Preview Comment on Pull Requests
Enable the Cloudflare Pages GitHub App to post deployment URLs as PR comments. Configure under Settings > Builds & deployments > Preview comment.
Pages Functions
Pages Functions provide server-side logic deployed alongside your static site. Place files in a functions/ directory at the project root.
Basic API Route
// functions/api/hello.ts
export const onRequestGet: PagesFunction = async (context) => {
return new Response(JSON.stringify({ message: "Hello from the edge" }), {
headers: { "Content-Type": "application/json" },
});
};
// functions/api/users/[id].ts — dynamic route parameter
export const onRequestGet: PagesFunction = async (context) => {
const userId = context.params.id;
return new Response(JSON.stringify({ userId }), {
headers: { "Content-Type": "application/json" },
});
};Middleware
// functions/_middleware.ts — runs before all routes
export const onRequest: PagesFunction = async (context) => {
const authHeader = context.request.headers.get("Authorization");
if (!authHeader || !authHeader.startsWith("Bearer ")) {
return new Response("Unauthorized", { status: 401 });
}
return context.next();
};Functions with Bindings
// functions/api/data.ts — using KV and D1 bindings
interface Env {
MY_KV: KVNamespace;
MY_DB: D1Database;
MY_BUCKET: R2Bucket;
}
export const onRequestGet: PagesFunction<Env> = async (context) => {
// Read from KV
const cached = await context.env.MY_KV.get("key");
if (cached) return new Response(cached);
// Query D1
const result = await context.env.MY_DB.prepare(
"SELECT * FROM items LIMIT 10"
).all();
// Cache in KV
await context.env.MY_KV.put("key", JSON.stringify(result.results), {
expirationTtl: 300,
});
return Response.json(result.results);
};Wrangler Configuration
# wrangler.toml — Pages project configuration
name = "my-site"
compatibility_date = "2024-09-01"
pages_build_output_dir = "dist"
# KV namespace binding
[[kv_namespaces]]
binding = "MY_KV"
id = "abc123def456"
# D1 database binding
[[d1_databases]]
binding = "MY_DB"
database_name = "my-app-db"
database_id = "xxxx-yyyy-zzzz"
# R2 bucket binding
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "app-assets"
# Environment variables
[vars]
API_BASE_URL = "https://api.example.com"Headers and Redirects
Custom Headers
# public/_headers
/assets/*
Cache-Control: public, max-age=31536000, immutable
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'
/api/*
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, OPTIONSRedirects
# public/_redirects
/old-page /new-page 301
/blog/:slug /posts/:slug 301
/docs/* https://docs.example.com/:splat 302
/home / 302Custom Domains
# Add a custom domain via Cloudflare dashboard:
# Pages project > Custom domains > Set up a custom domain
# Or via API
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/pages/projects/my-site/domains" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"www.example.com"}'CI/CD Integration
GitHub Actions
# .github/workflows/deploy.yml
name: Deploy to Cloudflare Pages
on:
push:
branches: [main]
pull_request:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build
- uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy dist --project-name=my-siteTroubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Build fails with out-of-memory | Build exceeds 1 GB RAM limit | Reduce dependencies; use NODE_OPTIONS=--max_old_space_size=768 |
| Functions return 404 | functions/ directory not at project root | Move functions/ to repo root, not inside src/ |
| Preview URL shows old content | Browser cache or stale deployment | Hard refresh; check deployment list for latest commit hash |
| Custom domain shows SSL error | DNS not proxied through Cloudflare | Enable orange cloud (proxy) on the CNAME record |
_headers file ignored | File not in build output directory | Place in public/ so it copies to dist/ during build |
| Bindings undefined in Functions | Missing wrangler.toml or dashboard config | Add bindings in wrangler.toml and redeploy |
| 1 MB function size limit exceeded | Too many dependencies bundled | Tree-shake; move large deps to KV or R2 |
Related Skills
- cloudflare-workers - Edge backend logic and API routes
- cloudflare-r2 - Object storage for assets and uploads
- cloudflare-zero-trust - Protect preview deployments with Access policies
- cdn-setup - General CDN configuration patterns
Related skills
FAQ
Can it deploy full-stack apps?
Yes. Pages Functions add server-side logic with KV, D1, and R2 bindings alongside the static site.
Does it support preview deployments?
Yes. Every non-production branch gets a unique preview URL automatically.