{
  "slug": "deploy-cloudflare-pages",
  "title": "Cloudflare Pages — global edge, free",
  "description": "Direct Cloudflare Pages API upload. 300+ edge PoPs, free tier covers most sites. The fastest path for pure-static content worldwide.",
  "category": "deployment",
  "order": 4,
  "locale": "en",
  "translationGroup": "e4055d5c-3e42-491d-a74c-63899fcc5cda",
  "helpCardId": null,
  "content": "## What it is\n\n**Cloudflare Pages (direct)** pushes your built site to Cloudflare's edge network via the Direct Upload API. No git push, no webhook relay, no wrangler CLI — just an HTTPS upload. Cloudflare serves the files from 300+ PoPs worldwide with automatic HTTPS and unlimited bandwidth on the free tier.\n\n> This replaces the legacy `Cloudflare (webhook)` provider, which only POSTed to a build hook URL. That one still exists for backwards compatibility, but new sites should pick `Cloudflare Pages (direct)`.\n\n## When to use it\n\n- Your site is static (no SSR, no custom server logic)\n- You want the fastest possible first-byte time globally (10–30 ms at edge)\n- You want the lowest cost ($0 on free tier for typical small sites)\n- You're OK with Cloudflare as a dependency (DNS optional, project can still use any registrar)\n\n## When NOT to use it\n\n- Your site is a Next.js SSR app — use Vercel, Fly.io (rebuild), or Cloudflare Workers.\n- You need write-at-runtime content storage (uploads, form submissions) — Pages is immutable static.\n- You're already committed to Fly for other services and want one hosting provider — use [Fly.io Live](/docs/deploy-fly-live).\n\n## How it works\n\n1. CMS admin builds your site locally (`deploy/`)\n2. Posts all files as `multipart/form-data` to `POST /accounts/:id/pages/projects/:name/deployments`\n3. Cloudflare processes the upload, creates a new deployment, and propagates to the edge\n4. The new version is live globally in ~3–10 seconds\n\nOn first deploy, the admin automatically creates the Pages project (type: Direct Upload). Subsequent deploys just add new deployments to the existing project.\n\n## Setup\n\n### 1. Get your Cloudflare credentials\n\n**Account ID** — Cloudflare dashboard → select any domain → right sidebar, copy the Account ID.\n\n**API token** — Cloudflare dashboard → My Profile → API Tokens → Create Token → Custom token with:\n\n- **Permissions**: Account → Cloudflare Pages → Edit\n- **Account resources**: Include → your account\n\nNo other scopes are needed. Save the token securely — it won't be shown again.\n\n### 2. Configure the provider\n\nSettings → Deploy → **Cloudflare Pages (direct)**. Provide:\n\n- **API token** — from step 1\n- **Account ID** — from step 1\n- **Project name** — lowercase, digits, hyphens (e.g. `my-site`). Auto-generated from your site name if left empty. Max 58 characters.\n\n### 3. Click Deploy\n\nFirst click creates the Cloudflare Pages project and uploads your files. You'll see the live URL: `https://<project-name>.pages.dev` (or your custom domain if configured).\n\n### 4. Custom domain (optional)\n\nCloudflare dashboard → Pages → your project → Custom domains → Set up a custom domain. Cloudflare handles DNS + certs automatically.\n\n## Payload format\n\nThe upload uses multipart form-data. Field names are paths with leading slash (e.g. `/index.html`, `/assets/app.js`). Binary files are sent as-is — Cloudflare handles content-type detection.\n\nThere's no HMAC signing on this provider — Cloudflare uses your Bearer token directly. Keep the token secret.\n\n## Rollback\n\nIn the Cloudflare dashboard, each deployment is listed under Pages → your project → Deployments. Click any historical deployment → Rollback. The Pages URL updates immediately.\n\nThe CMS admin doesn't expose Cloudflare rollback in UI yet — use the dashboard for now.\n\n## Limits (free tier)\n\n- **500 builds per month** — a build = one deploy. Most sites do 10–30/month.\n- **Unlimited requests** — no bandwidth caps.\n- **25 MB per file** — large videos should go to R2 or another CDN.\n- **20 000 files per deployment** — enough for any normal site.\n\nPaid Pro ($20/mo) raises the build limit to 5000/month. Most small sites never need to pay.\n\n## Comparison\n\n| | Cloudflare Pages | Fly.io Live | GitHub Pages | Vercel |\n|---|---|---|---|---|\n| Time per deploy | 3–10 s | 200 ms–1 s | 15–30 s | 20–60 s |\n| Global edge | Yes (300+ PoPs) | No | Yes (CDN) | Yes (Edge) |\n| Free tier | Generous | No | Yes | Yes (Hobby) |\n| SSR support | Workers (separate) | No | No | Yes |\n| Custom domain | Free, easy | Flyctl, requires DNS | Subpath friendly | Free |\n\n## Troubleshooting\n\n**\"project name invalid\"** — project names must be lowercase letters, digits, and hyphens (max 58 chars). The admin slugifies your site name — if that fails, enter a valid name manually.\n\n**\"deployment rejected\"** — Cloudflare returns a reason in the error. Common causes: oversized file (>25 MB), too many files (>20k), expired token.\n\n**\"account ID missing\"** — copy the Account ID exactly from the Cloudflare dashboard. It's 32 hex characters.\n\n## Related\n\n- [Fly.io Live](/docs/deploy-fly-live) — when you want everything on Fly\n- [Deploy settings](/docs/settings-deploy) — full provider reference\n- [Instant Content Deployment](/docs/instant-content-deployment) — the push-to-running-Next.js pattern, not relevant for static sites on Pages\n",
  "excerpt": "What it is\n\nCloudflare Pages (direct) pushes your built site to Cloudflare's edge network via the Direct Upload API. No git push, no webhook relay, no wrangler CLI — just an HTTPS upload. Cloudflare serves the files from 300+ PoPs worldwide with automatic HTTPS and unlimited bandwidth on the free ti",
  "seo": {
    "metaTitle": "Cloudflare Pages (direct) — webhouse.app Docs",
    "metaDescription": "Direct Cloudflare Pages API upload. 300+ edge PoPs, free tier, no CLI. The fastest path for pure-static content worldwide.",
    "keywords": [
      "webhouse",
      "cms",
      "cloudflare",
      "pages",
      "deploy",
      "edge",
      "cdn",
      "static"
    ]
  },
  "createdAt": "2026-04-16T12:00:00.000Z",
  "updatedAt": "2026-04-16T12:00:00.000Z"
}