Clean redirects on Cloudflare Pages

Diagram of 301 redirects toward the canonical domain
Diagram of 301 redirects toward the canonical domain

Moving a site from Vercel to Cloudflare Pages, I hit a surprise: the redirects I had in astro.config.mjs stopped working. Makes sense —that config is translated by the platform’s adapter, and in a static build with no adapter there’s nothing to apply it—. On Cloudflare the right place is another one, and it’s simpler.

_redirects: native 301s

Cloudflare Pages reads a _redirects file at the build root. Since Astro copies public/ into dist/, you just drop it there. One redirect per line: source, destination and status code.

# public/_redirects
/download        /resume          301
/es/descargar    /es/curriculum   301

These are real 301s (permanent), which is what you want for SEO when you move a URL. No HTML pages with meta-refresh.

www → apex: pick a canonical

The other classic: serve the site on a single hostname and redirect the other. I use the apex without www as canonical (it matches the canonical tag and the sitemap), and send www → apex with a 301.

If you don’t, www.yourdomain.com usually returns a Cloudflare 521 (“Web Server Is Down”): the www has proxied DNS but isn’t routed to any origin. It’s not a bug in your code —it’s routing—. You fix it with a Redirect Rule in Cloudflare (Rules → Redirect Rules), 301 and preserve path/query.

Conclusion

On static Cloudflare Pages, public/_redirects covers your route 301s, and a Redirect Rule canonicalizes www → apex. Less config than an adapter, genuinely permanent redirects, and you dodge the phantom 521 that scares you in SEO audits but isn’t your code’s fault.