---
title: "Redirects"
description: "Redirects and wildcard redirects."
requested_language: cs
language: en
translation_notice: "This page isn't translated yet"
url: https://docs.systhema.app/cs/payload/content/redirects
version: unreleased (main)
docs_index: https://docs.systhema.app/cs/llms.txt
---
> This page isn't translated yet. Showing English.


Enable the Redirects collection by passing `redirect: true` to `withSysthema()`:

```ts
const config = withSysthema(buildConfig({ /* ... */ }), {
  redirect: true,
})
```

This registers `@payloadcms/plugin-redirects`'s `redirects` collection. Editors author redirects in the admin panel under **Redirects**.

![The Redirects collection in Admin](./images/redirects.light.webp)

## Stored fields and access

Each row has `from`, a custom URL or document-reference destination, the redirect status and `preserveQueryString`. Creating, reading, updating and deleting redirect rules uses the corresponding `redirects.*` capabilities. Change and delete hooks revalidate the site so cached redirect behavior is refreshed. Reference destinations require a resolvable document path.

## Wildcard redirects

When a `from` path contains `*`, Systhema treats it as a wildcard redirect and matches it automatically — no toggle needed.

### `from` syntax

Each `*` captures part of the path. A `*` at the **end** of the pattern captures everything that follows, including slashes. A `*` with more pattern after it captures a **single** segment (no slashes).

| `from` pattern    | Matches                                                                                                                       |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `/blog/*`         | Everything under `/blog/` — `/blog/hello` **and** `/blog/2024/recap` (a trailing `*` captures the rest, including slashes)    |
| `/shop/*/reviews` | A single segment — `/shop/widget/reviews`, but not `/shop/a/b/reviews` (a `*` with more pattern after it matches one segment) |
| `/*/news/*`       | Two captures — first `*` (has `/news/…` after it) = one segment; second `*` (trailing) = the rest; reorder via `$1`, `$2`     |

### `to` syntax (custom URL target)

| Target value  | Behaviour                                            |
| ------------- | ---------------------------------------------------- |
| `/posts/*`    | Bare `*` — substituted with the first capture (`$1`) |
| `/posts/$1`   | Explicit numbered capture — same as bare `*`         |
| `/news/$2-$1` | Reorders two captures                                |

If the target is a **reference** (a Payload document relationship) rather than a custom URL, all matching paths redirect to that single document — no capture substitution.

### Worked example

| From        | To            | Incoming path       | Redirects to        |
| ----------- | ------------- | ------------------- | ------------------- |
| `/blog/*`   | `/posts/*`    | `/blog/2024/recap`  | `/posts/2024/recap` |
| `/*/news/*` | `/news/$2-$1` | `/world/news/recap` | `/news/recap-world` |

### Same-origin safety

A custom-URL target stays on your own site: if a captured value would turn the resolved target into an absolute (`http://…`) or protocol-relative (`//…`) URL, the redirect is rejected and the next rule is tried — a capture can't smuggle in an off-site destination. Intentional off-site redirects still work; declare the host in the target itself (e.g. `https://example.com/*`), so the off-origin part comes from your literal template rather than from a capture.

### Resolution order

Within the site catch-all, resolution runs:

1. **Exact redirects** (from the `redirects` collection, no wildcards) — matched first.
2. **Wildcard redirects** — matched next, most-specific rule wins (the rule with the most literal characters in `from` takes precedence).
3. **Page lookup** — only reached if no redirect matched.
4. **Post permalink lookup** — with the [Posts module](https://docs.systhema.app/cs/payload/posts.md) enabled, only when no page matched at the path.

So an authored wildcard redirect wins over still-existing content at the same path. With the Posts module enabled, a redirect's **reference** target can also point at a post — it resolves through the permalink engine.

### Status codes

308 permanent is the default. Editors can change it to 307 temporary per redirect on the standard Payload Redirects form.

### Preserve query string

Every redirect — exact and wildcard alike — has an **Advanced Settings** collapsible containing a **Preserve query string** checkbox (default **on**). When on, the incoming `?query=string` is carried over to the target URL — target params win on conflict. Uncheck it to drop the query string entirely.

> [!NOTE]
> Query-string preservation needs the `searchParams` prop on the site's catch-all route. New projects get it from the template; existing projects are updated automatically by a codemod during `systhema upgrade`. Without it, redirects still fire — the query string just isn't carried over.
>
> On a **statically generated** route the query string cannot be carried over at all, and Systhema skips it rather than failing the request. `searchParams` is a dynamic API, and the scaffolded catch-all exports `revalidate` (ISR) — reading one there aborts the render, which used to turn a matched redirect into a 500. The redirect itself always fires; only the incoming query is dropped. Draft-mode renders still preserve it. If a site genuinely needs query preservation on public redirects, its catch-all has to opt out of static generation (`export const dynamic = 'force-dynamic'`), trading ISR for it.

### Redirects and locales

With `locales` enabled, `from` and a custom `to.url` are localized: each locale has its own pair, so `/about` → `/contact` in English and `/rolunk` → `/kapcsolat` in Hungarian live on one row. An incoming request is matched against the `from` of **its own** locale only — a Hungarian path never matches an English `from`. Leave a locale's `from` empty and that row simply doesn't apply there.

## Related

- [Rendering pages](https://docs.systhema.app/cs/payload/frontend/rendering.md)
- [Revalidation](https://docs.systhema.app/cs/payload/frontend/revalidation.md)
- [Content localization](https://docs.systhema.app/cs/payload/localization.md)
