---
name: cloudflare-emdash-cms-deploy
description: Use when deploying an Astro + EmDash CMS site to Cloudflare — build downloads wrangler.jsonc / 404s at root, setup-redirect loops, blank CMS content, new collections, or D1+R2 admin setup. Deploys to Workers, not Pages.
license: MIT
tags: [cloudflare, workers, emdash, astro, cms, d1, r2, deployment, autohub]
agents: [claude-code, codex, autojack]
category: deployment
metadata:
version: "1.13.0"
capabilities:
network: true
filesystem: readwrite
tools: [Bash, Node, Read, Edit]
resources:
- path: references/project-setup.md
type: file
- path: references/deploy.md
type: file
- path: references/domain-dns.md
type: file
- path: references/cms-configuration.md
type: file
- path: references/branding.md
type: file
- path: references/troubleshooting.md
type: file
---Deploy Astro + EmDash CMS to Cloudflare Workers
Overview
EmDash (the Astro-based CMS) deploys to Cloudflare Workers, not Pages. @astrojs/cloudflare v13+ is Workers-only: astro build emits dist/client + dist/server with no _worker.js. A Cloudflare Pages project cannot run that output, so it serves the raw repo — the root URL downloads wrangler.jsonc (application/octet-stream) or 404s (no index.html). The fix is always: deploy as a Worker.
Repo + package identity (do not confuse)
| Thing | What it is |
|---|---|
| CMS | GitHub emdash-cms/emdash · npm emdash + @emdash-cms/* |
| Not this | generalaction/emdash (agentic IDE on emdash.ai) — different product |
Ignore npm [email protected] as "current": it is an older April publish; npm view emdash version is the source of truth for stable CMS releases (tags look like [email protected] on GitHub).
Deployment-correctness constraint (hard rule — read before touching wrangler)
Jack's standing rule for Cloudflare Pages: a project connected to GitHub (source.type == "github") is deployed by pushing to the connected repo, never by running wrangler pages deploy — a direct upload against a GitHub-connected project bypasses CI and produces split-brain deploys where the dashboard and git disagree.
This skill's corollary is stricter: EmDash cannot run on Pages at all (see Overview above), so the question of "push vs. direct-upload" never even applies to Pages for this stack — the answer is always a Worker. A Worker has no git-deploy by default either; wrangler deploy is a manual, explicit action unless you wire your own CI (references/deploy.md → Auto-deploy on merge). If you ever catch yourself about to run wrangler pages deploy against an EmDash repo, stop — that repo does not belong on Pages, full stop.
What are you trying to do?
- Stand up a brand-new EmDash project (resolve latest version, account preflight, first deploy, admin setup wizard) →
references/project-setup.md - Deploy or redeploy the Worker (recipe, wrangler commands, wiring CI auto-deploy) →
references/deploy.md - Attach a custom domain to an already-deployed Worker →
references/domain-dns.md - Configure CMS content (rendering model, adding a collection to a live site, menus/widgets/scheduled publishing, custom API routes, a plugin needing direct D1 access) →
references/cms-configuration.md - Brand / white-label the site (admin chrome, system emails, client-demo "Studio" branding, public SEO) →
references/branding.md - Something's broken (symptom → diagnosis, common mistakes table, verify commands, a real-world case study) →
references/troubleshooting.md
Quick preflight (before any deploy)
- R2 must be enabled on the account (dashboard-only, needs a card on file) —
10042errors mean it isn't. - D1 free tier caps at 10 databases — check capacity before creating one.
- Export a scoped
CLOUDFLARE_API_TOKEN— wrangler's stored OAuth token often lacks R2 scope. - The custom domain's zone must be one you control (grab its
zone_id).
Full detail, including the version-currency ritual that must run on every new project: references/project-setup.md.
References
references/project-setup.md— version resolution/pinning ritual, account preflight (R2/D1/token/zone), first-boot admin setup wizard and the prerender-before-setup trap.references/deploy.md— the deploy recipe (D1/R2 provisioning, build, dry-run,wrangler deploy, encryption key), and wiring GitHub Actions auto-deploy on merge.references/domain-dns.md— attaching a custom domain to a deployed Worker via the Cloudflare API.references/cms-configuration.md— entry-envelope rendering model, adding a 2nd/3rd content collection to a live site, menus/widgets/scheduled publishing, custom API routes and typed feeds, a plugin reading a custom D1 table.references/branding.md— site-identity D1 option vs. build-time admin config (two different knobs), rebranding system emails viaemail:deliver, client-demo white-labeling, public SEO.references/troubleshooting.md— symptom → diagnosis table, verify commands, the full common-mistakes table, and a real-world migration case study.