cloudflare-pages – DevOps & Infrastructure skill for AI agents
Deploy static sites and full-stack apps on Cloudflare Pages with previews, functions, and custom domains.
Install the cloudflare-pages skill with one command
Pick the tool you use, copy the command and paste it in your terminal. The skill lands in that tool's skills folder and is ready in your next session.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/cloudflare-pages-72e24.tgz | tar xz -C ~/.claude/skills
Call it in Claude Code: /cloudflare-pages – then describe the task you want done.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/cloudflare-pages-72e24.tgz | tar xz -C ~/.codex/skills
Call it in Codex: $cloudflare-pages – then describe the task you want done.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/cloudflare-pages-72e24.tgz | tar xz -C ~/.hermes/skills
Call it in Hermes Agent: /cloudflare-pages – then describe the task you want done.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/cloudflare-pages-72e24.tgz | tar xz -C ~/.deepcode/skills
Call it in DeepSeek: /cloudflare-pages – then describe the task you want done.
SKILL.md content
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
Pin a supported Wrangler/Node version; framework adapters and provider limits change. Full-stack Next.js requires the current supported Workers/OpenNext workflow rather than assuming the legacy next-on-pages adapter. Confirm account/project/environment before deploy/delete/domain changes; previews can expose private builds and need access control. _headers applies to static assets, not Functions responses: set security/CORS headers in Functions and implement OPTIONS as needed. Bindings/cache keys must be scoped to authorized users/tenants when data is private; the shared key sample is only for public data. The CI example needs trusted-branch secret boundaries and an explicit preview branch; do not deploy untrusted PR builds with production credentials.
- 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 inspect the actual result (tailing text is not JSON parsing)
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 static export | npm run build with export configuration | out |
| 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");
// validateBearerToken is application code: verify signature/issuer/audience/expiry
// or use Cloudflare Access validation; header presence is not authentication.
if (!authHeader || !(await validateBearerToken(authHeader, context.env))) {
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 | Inspect current platform limit and logs | Reduce build memory or use a supported build environment |
| 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/domain activation or certificate issue | Verify Pages domain status and official DNS requirements before cha
… (full content is in the download package)
Related skills
- pinggy-tunnel – Zero-install localhost tunnels over SSH via Pinggy.
- cloudflare-workers – Build and deploy edge functions with Cloudflare Workers and Wrangler. Use for APIs, cron…
- cloudformation – Deploy AWS resources with CloudFormation templates. Create stacks, use nested stacks…
- cloudish – Deploy a Dockerfile, source folder, or existing image to Cloudish as a running container…
- quantized-export – Export a promoted fine-tuned model in the right deployment format — merged safetensors…
- kubernetes-operator – Use when building a Kubernetes Operator — custom controllers that reconcile CRD state…
- kubernetes-operator – Use when building a Kubernetes Operator — custom controllers that reconcile CRD state…
- product-price-monitor – Watch product, flight, or listing prices; alert on target.