Alright, let’s talk about the _redirects file. This is one of those beautifully simple yet deceptively powerful tools Cloudflare Pages gives you. Forget wrestling with a convoluted config file or writing a Lambda function just to send someone from point A to point B. This is your old-school, text-file-having, no-nonsense solution.

The concept is dead simple: you create a file named _redirects (yes, with the underscore) in the root of your project’s build output. Inside, you write lines with three pieces: a source path, a destination, and a status code. It follows the same format Netlify uses, because why reinvent a perfectly good wheel?

Here’s the basic syntax for a single line: /old-path /new-path 301

The Core Syntax and Status Codes

Let’s break that line down. The first part is the path a visitor requests. The second is where you want to send them. The third is the HTTP status code, and this is where the magic (and the gotchas) live.

The status code isn’t just a number; it tells browsers and search engines how to handle the redirect. You’ll use two most of the time:

  • 301: Permanent Redirect. This is the gold standard. It tells Google, “Hey, this page has moved forever, update your index and pass along any SEO juice to this new URL.” Use this for… well, permanent moves.
  • 302: Temporary Redirect. Use this for A/B tests, temporary maintenance pages, or “hey, check out this new thing for a second.” Browsers won’t cache it as aggressively, and search engines won’t transfer page rank.

There are two other special ones that Cloudflare Pages supports that are incredibly useful:

  • 200: OK. Wait, that’s not a redirect! Ah, but in this context, it is. This is for rewrites. The user stays on the requested URL, but the content is served from a different path. This is your key to building single-page applications (SPAs) without hash routing.
  • 404: Not Found. You can trigger a custom 404 page based on a specific pattern. More on that later.
# Permanent move for a renamed blog post
/blog/my-awesome-post /blog/my-even-more-awesome-post 301

# Temporary redirect for a seasonal campaign
/summer-sale /campaigns/summer-2024 302

# Rewrite for SPA routing - user sees /app/settings but gets /index.html
/app/settings /index.html 200

# Specific 404 for a deleted product
/deleted-product /404.html 404

Splats and Placeholders

This is where it gets fun. You’re not limited to exact paths. You can use wildcards, called splats, to match entire segments of a URL. A splat is an asterisk (*). You can then use :splat in the destination to represent whatever was matched.

This is perfect for catch-all redirects or migrating entire sections of a site.

# Redirect all posts from an old blog structure to a new one
/blog/* /news/:splat 301

# A practical example: moving from a language subdirectory to a subdomain
# This redirects /fr/about to https://fr.mywebsite.com/about
/fr/* https://fr.mywebsite.com/:splat 301

# You can also use it for simple, greedy catches. This redirects any missed asset requests to a placeholder image.
/assets/* /images/placeholder.jpg 302

Be careful with the order of your rules, though. The file is processed from top to bottom, and the first matching rule wins. If you put a greedy splat like /* at the top, nothing below it will ever be reached. Always order your rules from most specific to most general.

The Critical Build Output Gotcha

Here’s the part that trips up absolutely everyone, so listen close: The _redirects file must be in your build output. Not in your source code. In the built site that gets deployed.

If you’re using a static site generator like Hugo, Gatsby, or Next.js (with static export), you usually configure it to copy the _redirects file from your source directory to the output public or dist folder. For other setups, you might need to write a simple build script to move it.

If you just add it to your project root and your build tool ignores it, you’ll spend 45 minutes yelling at Cloudflare, convinced it’s broken, when the problem is your build process never included the file. I’ve been there. It’s not fun. Double-check that the file is in the final uploaded bundle.

When to Use It (And When to Not)

The _redirects file is brilliant for its simplicity. Use it for:

  • Simple path-to-path redirects.
  • SPA rewrites.
  • Bulk redirects using splats.
  • The occasional custom 404.

But it has limits. It can’t handle complex logic. You can’t check for cookies, geolocation, or A/B test groups. You can’t do a redirect based on the result of a computed value. For those scenarios, you’ll need to graduate to Cloudflare Pages’ more powerful (and complex) _routes.json config or Cloudflare Functions. But for probably 90% of your redirect needs, _redirects is your quick, reliable, and brilliantly straightforward friend. Just remember to put it in the right damn folder.