---
url: https://void.cloud/guide/edge/redirects.md
description: >-
  Redirect requests from void.config.ts. Map a source pattern to a destination
  and an optional status code.
---

# Redirects

Define URL redirects in [`void.config.ts`](../../reference/config) using the `routing.redirects` field. Keys are source URL patterns, values are destination strings or objects with an explicit status.

```json
{
  "routing": {
    "redirects": {
      "/old": "/new",
      "/blog/*": { "to": "/posts/:splat", "status": 301 }
    }
  }
}
```

## Rules

* **Source patterns** start with `/`. `*` matches any characters including `/`.
* **Destinations** can be strings (default `302`) or objects with `to` and optional `status`. Supported statuses: `301`, `302`, `303`, `307`, `308`.
* `:splat` in the destination is replaced with the portion of the path matched by `*` in the source pattern.
* Destination query strings are merged into the `Location` header (the destination's parameters take precedence on per-key conflict). To drop the incoming query, write an explicit reset like `?`.
* `c.redirect()` in a handler, loader, or middleware sends that location unchanged and does not append the request query. A named action still drops its action key when the browser follows with GET, and keeps the page's other parameters. See [`c.redirect()`](../../reference/api/rewrites.md#c-rewrite-destination).
* When multiple rules match, the **first match wins**. Put specific patterns before catch-all patterns.
* Redirects are evaluated **before** the request reaches the worker, so they short-circuit static asset serving, ISR, and SSR.

## Domain-level redirects

Prefix a source with `https://host` to redirect only requests to that domain:

```json
{
  "routing": {
    "redirects": {
      "https://www.example.com/*": "https://example.com/:splat",
      "https://old-marketing.com/*": "https://example.com/:splat"
    }
  }
}
```

The `_redirects` file accepts the same syntax:

```
https://www.example.com/*  https://example.com/:splat  301
```

Path-only sources apply to every domain on the project. Host-prefixed sources apply only to the named domain.

The source must use `https://` and a literal hostname without wildcards or a port. Add the domain to your project with `void domain add` before deploying the rule. A domain awaiting certificate verification starts redirecting once it becomes active.

## HTTP to HTTPS

Set `routing.alwaysUseHttps` to redirect HTTP requests to HTTPS:

```ts
import { defineConfig } from 'void/config';

export default defineConfig({
  routing: {
    alwaysUseHttps: true,
  },
});
```

Void returns a permanent `308` redirect that preserves the path, query string, and request method. The option defaults to `false`. Localhost and loopback addresses stay on HTTP for local development and previews.

This option requires the Cloudflare target and works for Void apps and static sites on either deployment platform.

For direct Cloudflare deployments, also enable [Always Use HTTPS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/) on your zone to cover assets served directly by Cloudflare.

For direct Cloudflare deployments of SvelteKit, Nuxt, Astro, Analog, TanStack Start, React Router, or vinext, configure HTTPS in the framework or your Cloudflare zone. Use `routing.alwaysUseHttps` only for their static builds, deployed with `--dir` or `inference.appType`.

## Framework `_redirects` files

Void reads `_redirects` files produced by supported frameworks. You can also place one in Vite's `publicDir`:

```text
/old-page  /new-page     301
/blog/*    /posts/:splat 301
```

Rules in `void.config.ts` take precedence over file rules. Use `200` for a fallback or `200!` for a [rewrite](./rewrites#redirects-file). Redirects don't need the `!` suffix.
