Skip to content
Late Summer Sale: 20% OFF every theme and the All-Access Pass until August 31. Browse themes
AeroLaunch
All articles
Guides August 13, 2026 5 min read

How to Deploy an Astro Site to Cloudflare (Pages or Workers)

Two ways to deploy the Astro web framework to Cloudflare - Pages with git-push deploys, or a Worker with static assets - plus the SSR adapter, custom domains, and the gotchas we hit shipping 25 production sites.

A By AeroLaunch

The Astro web framework and Cloudflare are a natural pair: Astro builds your site down to static HTML, and Cloudflare serves static files from its edge in every region for free. We run this exact stack in production - this marketing site is a Worker with static assets, and all 25 of our theme previews deploy to Cloudflare Pages - so this guide is the setup we actually use, gotchas included.

There are two ways to put an Astro site on Cloudflare, and both are first-class:

PathDeploy triggerBest for
Cloudflare Pagesgit push (or CLI)Fastest start, per-branch previews
Worker with static assetswrangler deployOne config, bindings (D1, KV, R2), full control

Path 1: Cloudflare Pages

Pages is the shortest route from repository to URL.

Git integration (the usual way)

  1. Push your Astro project to GitHub or GitLab.
  2. In the Cloudflare dashboard: Workers & Pages, then Create, then Pages, then Connect to Git.
  3. Pick the repository and set two fields:
    • Build command: npm run build (or pnpm build)
    • Build output directory: dist
  4. Deploy.

Cloudflare detects Astro and pre-fills these for most repositories. From then on, every push to the production branch deploys live, and every push to any other branch gets its own preview URL - <hash>.<project>.pages.dev - which is the single best feature of Pages for reviewing changes before they ship.

CLI deploys with wrangler

No git integration needed - you can push a built folder directly:

Terminal window
npx astro build
npx wrangler pages deploy dist

One gotcha we hit across our theme fleet: wrangler maps your local git branch name to the deployment environment. If the Pages project’s production branch is main but your local branch is master, the upload silently lands as a preview deployment and production never updates. Pin it explicitly:

Terminal window
npx wrangler pages deploy dist --branch=main

Path 2: a Worker with static assets

Workers used to mean “serverless functions”; since Cloudflare added static assets, a Worker can also just serve your dist folder - and this is the setup Cloudflare steers new projects toward. Everything lives in one wrangler.jsonc:

{
"name": "my-astro-site",
"compatibility_date": "2026-04-01",
"assets": {
"directory": "./dist",
"not_found_handling": "404-page",
"html_handling": "auto-trailing-slash"
}
}

Then:

Terminal window
npx astro build
npx wrangler deploy

That is the whole pipeline. not_found_handling: "404-page" wires up Astro’s src/pages/404.astro, and html_handling controls trailing-slash behavior so /about and /about/ resolve consistently.

Why choose this over Pages? One reason: bindings. The same config file attaches a D1 database, KV namespace, R2 bucket, or cron trigger the day you need one. Our own site started as pure static and later grew a form endpoint backed by D1 - no migration, just a main entry and a binding added to the existing config.

Two hard-won notes from running this in production:

  • Custom domains in routes are declarative. The list you deploy is the complete list; any domain missing from it gets detached. We once listed only www and knocked the apex domain offline. Always declare both:
"routes": [
{ "pattern": "example.com", "custom_domain": true },
{ "pattern": "www.example.com", "custom_domain": true }
]
  • If you use pnpm, run pnpm run deploy, not pnpm deploy. Bare pnpm deploy is a pnpm built-in command for workspace publishing and fails with a confusing error. The run makes it execute your package script.

Server-side rendering: the Cloudflare adapter

Everything above assumes a static build, which is the right default for the Astro web framework - and for most content sites, the story ends there. When some routes genuinely need to render per-request (auth, form handling, API endpoints), add the adapter:

Terminal window
npx astro add cloudflare

This installs @astrojs/cloudflare and wires it into your config. Keep prerendering as the default and opt individual routes into SSR, so the static pages stay static and fast:

src/pages/api-driven-page.astro
---
export const prerender = false;
---

SSR pages run inside the Workers runtime, which means your server code can reach the same bindings - D1, KV, R2 - directly from Astro.locals. And if you are on Astro 7.2 and never touch sessions, set session: false to shrink the server bundle; we covered that in What’s New in Astro 7.2.

Custom domains

  • Pages: project dashboard, Custom domains, add example.com and www.example.com. If the domain’s DNS is already on Cloudflare, records are created for you.
  • Workers: declare them in routes as shown above and deploy. Same rule applies - the list is complete and authoritative.

Either way, TLS certificates are provisioned automatically and renew themselves.

The checklist

  1. npx astro build - confirm dist/ builds clean locally.
  2. Pick a path: Pages (git push, previews) or Worker with static assets (one config, bindings).
  3. Deploy: git push, or npx wrangler pages deploy dist --branch=main, or npx wrangler deploy.
  4. Attach the custom domain - both apex and www.
  5. Ship the next change with a one-line deploy.

The build output of the Astro web framework - plain HTML, CSS, and a little JavaScript where you asked for it - is the easiest possible thing to host, and Cloudflare’s free tier serves it globally without a server to babysit. Every AeroLaunch theme is a standard Astro project with dist output, so any of the 25 deploys to Cloudflare exactly as described here: pick a theme, drop in your content, and you are two commands from live.

Frequently asked questions

Is Astro a web framework? +

Yes. Astro is a web framework built for content-driven websites - it renders your pages to static HTML at build time and ships zero JavaScript by default, which is exactly the workload edge platforms like Cloudflare are optimized to serve.

Should I use Cloudflare Pages or Workers for an Astro site? +

Both work well. Pages is the fastest start: connect the git repository, set the build command, and every push deploys with per-branch preview URLs. Workers with static assets is Cloudflare's current direction for new projects and gives you one config file that also covers bindings like D1, KV, and R2 when you need a backend later. If you are unsure, start with Pages; moving to a Worker later is straightforward.

Do I need the Cloudflare adapter to deploy Astro? +

Only for server-side rendering. A fully static Astro site is just a dist folder of HTML and assets - no adapter, no runtime. You add @astrojs/cloudflare only when some routes need to render on request, for form handling, personalization, or API endpoints.

How do I deploy an Astro site to Cloudflare Pages from the command line? +

Build first, then push the output folder: npx astro build followed by npx wrangler pages deploy dist. Pass --branch=main if your local branch name differs from the project's production branch, otherwise the upload lands as a preview deployment instead of production.

Can I use a custom domain with an Astro site on Cloudflare? +

Yes, on both paths. Pages projects attach custom domains from the dashboard. Workers declare them in wrangler config under routes - and that list is declarative, so always list every domain you serve, including both the apex and www.

Ship it faster

Start from a production-ready Astro theme

Skip building the design from scratch. These themes are full Astro 7 + Tailwind v4 projects you own outright - and you can edit them visually, no code, with the AeroLaunch builder.