skills/cloudflare-pages-cicd/SKILL.md
Cloudflare Pages CI/CD with preview environments, edge functions, and Wrangler automation. Activate on: Cloudflare Pages, Wrangler deploy, preview environment, edge function, Pages project, Cloudflare Workers integration, custom domain on Pages. NOT for: Worker-specific development (use cloudflare-worker-dev), DNS management (use devops-automator), full-stack app frameworks (use vercel-deployment).
npx skillsauth add curiositech/windags-skills cloudflare-pages-cicdInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Expert in deploying and automating Cloudflare Pages projects with preview environments, edge functions, and Wrangler CLI.
Request processing needs:
├─ Static assets only → Pages (no functions needed)
├─ <10ms CPU + simple API routes → Pages Functions
├─ 10-50ms CPU + stateful operations → Workers
└─ >50ms CPU or heavy processing → Queues + Workers
Deployment model:
├─ Git-based with previews → Pages Git integration
├─ CI/CD with artifact upload → `wrangler pages deploy`
├─ Local development testing → `wrangler pages dev`
└─ Multi-environment promotion → Direct upload with branch targeting
Framework detected:
├─ Next.js → Use @cloudflare/next-on-pages adapter
├─ Astro/SvelteKit/Remix → Native Cloudflare support
├─ Static site generator → Standard build command
└─ Custom build → Specify exact build command + output dir
Environment variables needed:
├─ Public vars → [vars] in wrangler.toml
├─ Secrets → `wrangler pages secret put`
├─ Preview-specific → Environment-based binding IDs
└─ Build-time only → CI/CD environment variables
Data persistence requirements:
├─ Cache/sessions → KV (global, eventual consistency)
├─ Relational data → D1 (SQL, strong consistency per location)
├─ File storage → R2 (S3-compatible object storage)
├─ Real-time state → Durable Objects
└─ External APIs → Service bindings or fetch()
Preview environment isolation:
├─ Development → Separate binding IDs for all resources
├─ Staging → Shared read-only or staging-specific resources
├─ Production → Live binding IDs
└─ Local dev → `--local` flag with local SQLite/memory KV
Symptoms: Builds consistently timeout at 20+ minutes, "Build exceeded time limit" Root cause: Inefficient dependency installation or missing build cache Fix:
node_modules caching in CI/CDnpm ci instead of npm install--no-bundle
Detection: grep "Build exceeded" build-logs.txtSymptoms: Functions work locally but fail in production with "undefined is not a function" Root cause: Missing environment variables or incorrect binding names Fix:
wrangler.toml matches dashboard bindings exactlywrangler pages deployment tail to debug runtime errorsSymptoms: Preview deployments show production data or fail authentication Root cause: Shared binding IDs between environments Fix:
Symptoms: "Memory limit exceeded" errors, slow response times >5s Root cause: Loading large datasets in Functions (128MB limit) Fix:
Memory usage exceeded in Function logsSymptoms: Manual deploys work but Git pushes don't trigger builds Root cause: Webhook disconnected or incorrect build settings Fix:
Scenario: Next.js app needs branch-based previews + production deploys
Step 1: Decision Points Navigation
Step 2: GitHub Actions Workflow
name: Deploy to Cloudflare Pages
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Cache dependencies
uses: actions/cache@v3
with:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }}
- name: Install and build
run: |
npm ci
npx @cloudflare/next-on-pages
- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy .vercel/output/static --project-name=my-app --branch=${{ github.ref_name }}
- name: Comment PR with preview URL
if: github.event_name == 'pull_request'
run: |
PREVIEW_URL="https://${{ github.sha }}.my-app.pages.dev"
gh pr comment ${{ github.event.number }} --body "🚀 Preview: $PREVIEW_URL"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Step 3: Expert vs Novice Catches
Step 4: Quality Gate Validation
[ ] wrangler.toml has compatibility_date within 6 months
[ ] All bindings have separate preview/production IDs configured
[ ] Git integration connected and webhook responding to pushes
[ ] Preview deployments generate unique URLs for each branch/commit
[ ] Build command produces output in specified directory
[ ] Pages Functions use TypeScript with proper Env interface
[ ] Custom domain configured with SSL certificate active
[ ] Build time consistently under 3 minutes
[ ] Environment variables properly scoped (secrets vs vars)
[ ] Deployment notifications integrated with team communication
[ ] Function response times <100ms for simple operations
[ ] Static assets served with proper caching headers
Don't use Cloudflare Pages for:
cloudflare-worker-dev for advanced Workers features, WebSockets, or CPU-intensive tasksdevops-automator for Cloudflare DNS API operations and domain configurationvercel-deployment for frameworks requiring Node.js runtime or complex server logicDelegate to:
data-ai
license: Apache-2.0 NOT for unrelated tasks outside this domain.
development
Use when designing caching strategies (cache-aside, write-through, write-behind), implementing distributed locks, building rate limiters, leaderboards, real-time streams (XADD/consumer groups), pub/sub, or tuning eviction policies. Triggers: thundering-herd on cache miss, dogpile on key expiry, Redlock vs SET-NX-PX choice, sliding-window rate limiter, hot-key on a single cluster slot, big-key blowup, MULTI/EXEC across slots, KEYS in production. NOT for Redis Cluster operations/admin (different domain), embedded KV (SQLite, leveldb), in-process LRU caches, or Memcached.
tools
Drawing the `'use client'` boundary correctly in React Server Components apps (Next.js App Router, RSC frameworks) — leaf-pushing, slot composition, serialization rules, and environment poisoning prevention. Grounded in react.dev and Next.js 16 docs.
development
Use when designing rate limiting for an API, choosing between token bucket / sliding window / leaky bucket / fixed window, implementing it in Redis, deciding edge (Cloudflare/Upstash) vs origin enforcement, sizing per-user vs per-IP vs per-endpoint quotas, returning the right 429 response with Retry-After, or fixing the boundary-burst bug in fixed-window limiters. Triggers: 429 too many requests, INCR + EXPIRE, ZADD + ZREMRANGEBYSCORE + ZCARD, X-RateLimit-Remaining header, Cloudflare WAF rate limiting rules, Upstash @upstash/ratelimit, leaky bucket shaping vs policing, distributed rate limiter consistency. NOT for DDoS mitigation specifically (different scale), CAPTCHA / bot management, full WAF design, or per-user quota billing.