Domains, redirects, and headers
Configure static redirects and headers
Use Pages routing files for deliberate URL changes and response headers without adding a Function to every request.
Pages reads two plain-text files from your build output: _redirects and _headers. They handle most routing and header jobs at deploy time, with no code running per request.
The location matters. The files must end up in the deployed output directory. A _redirects sitting in your repository root while the build deploys dist/ is silently ignored. Put it in your static assets folder so the build copies it, and check the deployed site, not your source tree.
Redirects
One rule per line: source, destination, status.
/old-pricing /pricing 301
/blog/* /articles/:splat 301
The * captures the rest of the path and :splat reinserts it, so /blog/hello becomes /articles/hello.
Order and shape matter. Keep exact redirects before broad wildcard rules. Pages applies static rules first, and a splat rule placed too early can shadow the rules after it.
There are hard limits too. At the time of writing, a file can hold 2,000 static rules but only 100 dynamic (*) rules. A site that generates thousands of wildcard rules will find some of them silently inert.
A redirect changes navigation. It does not carry a request body along. Redirecting a form POST with a 301 typically turns it into a GET and drops the payload.
Headers
_headers attaches response headers to paths:
/assets/*
Cache-Control: public, max-age=31536000, immutable
/*
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Use headers for cache policy and browser security whenever static configuration is enough. Long-lived caching belongs on fingerprinted assets whose names change on every build.
Be careful with HTML. Don’t apply long-lived caching to it until you understand release freshness. An HTML page cached for a year keeps referencing asset names from a year ago.
Verify the deployed result
Test the deployed result, on both preview and production:
curl -I https://my-site.pages.dev/old-pricing
# HTTP/2 301
# location: /pricing
curl -sI https://my-site.pages.dev/ | grep -i x-content-type-options
# x-content-type-options: nosniff
Try this: add one permanent old-path redirect and one security header to a practice project, then test both on the preview deployment before the production one.
Lesson completed