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