Deploy the output Astro already gives you
A content-led Astro project does not need a server merely because it is going to production. Astro’s default static output creates HTML and assets at build time. Cloudflare can distribute those files globally through Workers Static Assets or Pages.
This guide uses Workers Static Assets because it provides a current, explicit repository-to-edge configuration through Wrangler. If an existing project already uses Cloudflare Pages successfully, do not migrate it just to follow a different tutorial. Preserve the deployed architecture unless a real requirement justifies the change.
The important decisions are stable across both paths: build the right files, cache each artifact appropriately, keep index signals consistent, protect credentials, and verify the real domain after publication.
Choose the Cloudflare path from the existing project
Cloudflare has more than one way to host an Astro project. Pages remains a valid deployment target. Workers Static Assets places static files and optional Worker logic in the Workers platform. The correct choice begins with what the repository and account already use.
Inspect before changing anything:
npm run build
npx wrangler --version
npx wrangler whoami
Run only authenticated read checks that are allowed in the environment. Inspect wrangler.jsonc or wrangler.toml, package scripts, Git workflows, and the Cloudflare project name. Determine whether production deploys directly through Wrangler or through a connected build. Confirm the canonical domain and production branch.
Do not add an Astro Cloudflare runtime adapter to a fully static site merely because the host is Cloudflare. The adapter is for on-demand rendering and runtime capabilities. Static Assets can serve the existing dist output directly.
If the site later needs request-time personalization, authenticated endpoints, or server-managed data, revisit the decision as architecture work. Do not smuggle SSR into a deployment patch.
Confirm the Astro output mode
For a static marketing or editorial site, astro.config can remain simple:
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://example.com',
output: 'static',
trailingSlash: 'always',
integrations: [sitemap()],
});
Set site to the canonical production origin. Astro integrations and URL helpers use it when generating absolute URLs. Choose one trailing-slash policy and make internal links, canonicals, redirects, and sitemap entries agree.
Run the repository’s real build command, usually:
npm run build
The default output directory is dist. Inspect it. Confirm representative routes have index.html, fingerprinted assets resolve, the 404 document exists, and the generated sitemap contains only indexable production pages.
Use a clean production build for release evidence. A stale dist directory can contain routes removed from the current source, depending on how the build is invoked. The framework build normally manages its output, but confirm the repository script rather than deleting broad directories by habit.
Check representative files directly:
find dist -maxdepth 3 -name 'index.html' | sort
rg -n '<link rel="canonical"|<meta name="robots"' dist
rg -n '<script[^>]+src=' dist
Target searches keep the review readable. Use an HTML parser for a production-grade sitewide audit; regular expressions are useful for reconnaissance, not full HTML validation.
Configure Workers Static Assets
Wrangler connects the project configuration to Cloudflare. A static-only site can use a small wrangler.jsonc:
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "example-site",
"compatibility_date": "2026-09-04",
"assets": {
"directory": "./dist",
"not_found_handling": "404-page"
}
}
Use the project’s current compatibility date policy. Do not copy the date above indefinitely. Validate the configuration against the installed Wrangler version.
The assets.directory value must point to built output, not source files. 404-page tells Static Assets to use the closest 404.html document for missing routes while preserving not-found behavior. Test that behavior after deployment; a pretty page returning 200 is still an incorrect 404.
If the project uses a Git-based Cloudflare build, configure the production branch, build command, and output directory in that existing setup. Keep wrangler.jsonc in the repository so infrastructure expectations remain visible to future contributors.
Wrangler configuration should have one clear owner. Validate the JSONC against the installed Wrangler schema. Keep the Worker name stable once custom domains and build settings depend on it. Use environment-specific configuration only when the project actually has distinct preview and production behavior.
Static Assets uses asset-first routing by default: a matching file can be served without running Worker code. Preserve that efficient path for a static site. Settings such as run_worker_first are useful when a Worker must inspect particular requests, but applying Worker logic to every asset can change latency and header behavior. Introduce it for a named requirement, not preemptively.
For directory-style Astro routes, verify how asset HTML handling interacts with the project’s trailing-slash policy. Request both the chosen canonical form and its alternative. One should be canonical; the other should resolve predictably without creating two indexable documents.
Add headers deliberately
Workers Static Assets supports a _headers file for static responses. Place it in Astro’s public directory so it is copied to the root of dist.
A conservative starting point might look like this:
/*
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
X-Frame-Options: DENY
Permissions-Policy: camera=(), microphone=(), geolocation=()
/_astro/*
Cache-Control: public, max-age=31536000, immutable
Do not paste a Content Security Policy from another site. Inventory the scripts, styles, fonts, images, forms, analytics, and payment destinations this project actually uses. Start restrictive, test production, and document every allowed origin.
Enable HSTS only after HTTPS and all required subdomains are ready for it. The browser remembers HSTS. Treat a long duration and includeSubDomains as an operational decision, not boilerplate.
Workers Static Assets applies _headers only to static asset responses. If the project later introduces Worker-generated responses or runs the Worker before assets, attach required headers in Worker code for those responses. Recheck the security model after any move from static delivery to runtime logic.
Prevent preview hosts from competing with the custom domain. Cloudflare documents hostname-specific _headers rules for applying a search-engine directive to workers.dev preview URLs. Configure that rule for the actual preview hostname and verify it does not affect the production custom domain. A canonical tag alone is not a staging access policy.
Define redirects as content operations
Static Assets supports a _redirects file in the asset directory. In Astro, author it under public so the build copies it to dist. Use redirects for approved URL moves, legacy paths, and one canonical host or slash policy where the platform configuration calls for it.
Keep the map narrow and testable:
/old-guide/ /guides/current-guide/ 301
/launch-offer/ /#pricing 302
Choose permanent or temporary status from the real content decision. A campaign detour is not automatically permanent. A retired article should not redirect to the home page just to avoid a 404; redirect only when the destination satisfies the same user need.
Check for loops, chains, duplicate source paths, and destinations that themselves redirect. Redirects take precedence over _headers matching, so verify the final response rather than expecting the source path’s header rule to survive.
Cache immutable assets, not mistakes
Astro fingerprints generated assets under paths such as /_astro/. Those filenames change when content changes, which makes long-lived immutable caching appropriate.
HTML has different needs. A new deploy can replace it at the same URL, so forcing a one-year browser cache on documents can keep stale pages alive. Let the platform’s asset behavior work unless the project has measured reasons for custom HTML caching.
Fonts and manually copied public assets deserve inspection. A file at /fonts/site.woff2 may keep the same URL across releases. If it receives immutable caching, changing its bytes without changing its filename can produce mixed versions. Either fingerprint it through the build or version the public path.
The AI website performance article explains why edge delivery helps only after image, font, JavaScript, and third-party decisions are under control.
Compression is another edge responsibility worth verifying, not assuming. Request representative HTML, CSS, JavaScript, SVG, and font assets with realistic Accept-Encoding values. Check the response encoding, content type, cache control, and Vary behavior. Do not manually precompress files unless the platform path and project requirements call for it.
Keep performance validation tied to the artifact. A globally distributed 600-kilobyte client bundle is still a 600-kilobyte client bundle. Cloudflare reduces delivery distance; Astro’s static architecture and project discipline reduce what must be delivered and executed.
Keep authentication out of the repository
Use the environment’s authenticated Cloudflare workflow. Do not paste API tokens into Wrangler files, shell history, build logs, or documentation. Scope deployment credentials to the correct account and project. If authentication is missing, report the exact blocker rather than creating a replacement account or publishing under a personal project.
Before any deploy, resolve the target with read-only checks:
- current Cloudflare account;
- Worker or Pages project name;
- production branch;
- canonical domain;
- existing custom-domain mapping;
- DNS records the release actually needs.
A static site deploy should not require changes to MX, SPF, DKIM, or DMARC records.
Attach the custom domain without collateral DNS changes
Workers supports custom domains and routes. Follow the existing project’s routing model. Confirm the zone is active in the intended account and identify whether the apex, www, or both should resolve. Pick one canonical host. Redirect the alternate deliberately and ensure metadata uses the final host.
Do not delete or replace unrelated DNS records. Website work may need an apex or www record and Cloudflare’s Worker routing association; it does not grant a reason to edit mail, verification, or service records. Capture the previous website-related state before changing it so rollback is possible.
After attaching the domain, allow for DNS and certificate provisioning state. Check the hostname with Cloudflare and then with an external DNS query. An active Worker deployment on workers.dev does not prove the custom domain points to that deployment.
Certificate readiness, redirect behavior, and the canonical host should all be verified over HTTPS before enabling a strict long-lived HSTS policy.
Use a controlled release sequence
A dependable release has discrete gates:
install dependencies
→ framework and type checks
→ content and link validation
→ production build
→ inspect git diff and status
→ commit and push through the approved branch
→ Cloudflare deploy or connected build
→ production verification
If the current repository uses direct Wrangler deployment, the command is commonly:
npx wrangler deploy
Run the configured package script when one exists. It documents the supported path and pins behavior to the project’s dependencies. Preview deployments are useful, but they should carry an index policy that prevents an alternate host from competing with the canonical domain.
With Workers Builds, the repository connection can run the project build and deploy when the configured branch changes. Confirm the install command, build command, deploy command, root directory, environment variables, and branch policy in the existing build configuration. A green Git push is not proof that Cloudflare built the same commit; record the deployment identifier and source revision.
Use least-privilege credentials for automated deployment. The token should belong to the intended account and project scope. Rotate or replace broad temporary credentials through the team’s secret store, not a tracked .env file. Never print tokens while diagnosing authentication.
If a push is supposed to trigger production, do not also run a direct deploy casually. Two release paths make it harder to know which commit is live. Choose the documented path and verify its result.
Verify the public site, not the dashboard
A successful Cloudflare status does not prove the website is correct. Request the real production domain and test representative route families.
At minimum, verify:
| Check | Expected result |
|---|---|
| Home and key routes | 200, correct HTML and CSS |
| Missing route | 404 with the designed document |
| Canonical | Absolute URL on the chosen host and slash format |
| Robots | Production content allowed; previews and drafts excluded |
| Sitemap | Valid XML containing indexable canonical routes only |
| Structured data | Valid JSON that matches visible content |
| Assets | Correct content types and cache behavior |
| Security headers | Present without blocking required resources |
| Purchase link | Correct destination, no accidental test URL |
Also inspect a narrow viewport, keyboard navigation, and a cold load. The production-ready AI website checklist covers the wider release contract.
Useful headless checks include:
curl -sS -I https://example.com/
curl -sS -I https://example.com/route-that-does-not-exist/
curl -sS https://example.com/robots.txt
curl -sS https://example.com/sitemap-index.xml
Follow redirects when testing final content, but also inspect the first response so chains remain visible. Parse the production HTML to confirm the canonical and structured data. Request a fingerprinted asset separately and verify its cache header. Check the purchase destination without initiating a transaction.
Run representative link checks against the custom domain, not only workers.dev. If the site has hubs, guides, comparisons, audience pages, and problem pages, test one of each. Shared templates reduce the sample size needed for visual review, but route generation and content links still need full automated coverage.
Troubleshoot by deployment layer
Wrangler says the asset directory does not exist
Run the production build first and confirm assets.directory is relative to the Wrangler configuration or command context expected by the installed version. Do not point Cloudflare at src or public; the host needs the final Astro output.
The Worker deploys, but the domain shows another site
Check the deployed Worker name, account, custom-domain association, DNS state, and production route. Compare the deployment revision with the local commit. Purging cache is not the first response to a routing mismatch.
Every missing route returns 200
Confirm not_found_handling is 404-page, not single-page-application behavior. Ensure dist/404.html exists. Test an unknown nested path on the production host and inspect the status without relying on what the browser displays.
Security headers appear on assets but not an API response
_headers applies to static assets. Responses produced by Worker code need headers attached in that code. Map which layer served the request before changing the file.
New HTML is live but styling is stale
Inspect asset URLs in the document. Fingerprinted files should change when their contents change. If a stable public asset was cached as immutable, version its URL or correct the cache policy. Confirm the new asset exists before purging.
The sitemap uses the preview hostname
Check Astro’s site setting and any environment-specific origin logic. Build with the production configuration, inspect the XML before deploy, and make sure the canonical helper uses the same origin. Do not string-replace the hostname in generated files as a release step.
A connected build does not start
Verify the Git provider connection, watched branch, root directory, and build triggers. Confirm the pushed commit reached the expected private remote. If authentication is missing, report that exact boundary rather than creating a second project with different ownership.
Avoid infrastructure theater
Cloudflare offers a large platform. A static Astro site does not need to use all of it. Add a Worker function, server runtime, database, queue, or edge personalization only when the product requirement demands one.
For a mostly static site, the strongest architecture can be unremarkable: Astro builds files, Cloudflare serves them, Git records the configuration, and a short validation suite proves the public result. That simplicity is a performance feature and an operational one.
Sources
Primary documentation was checked on the dates below. Product behavior can change; follow the source for the current implementation.
- Deploy your Astro site to Cloudflare Astro Documentation Accessed
- Static Assets Cloudflare Developers Accessed
- Wrangler configuration Cloudflare Developers Accessed
- Static Assets headers Cloudflare Developers Accessed
- Static Assets redirects Cloudflare Developers Accessed
- Workers Builds Cloudflare Developers Accessed
- Custom Domains Cloudflare Developers Accessed