Skip to main content
View as Markdown

URL Redirects

Restructuring a site retires URLs. Without a redirect the only possible answer at a retired path is a 404, and every indexed link, bookmark and backlink pointing there breaks.

The redirects array declares those retired paths and where each one now lives:

redirects:
  - from: /products/platform
    to: /
  - from: /products/partner
    to: /partner
  - from: /login
    to: /_admin/login
    status: 302

Rule Properties

Property Description
from Root-relative path to redirect away from. Must start with / and contain no whitespace, ? or #.
to Where to send the visitor — a root-relative path, or an absolute http(s):// URL to hand off to another origin.
status 301 (default), 302, 307 or 308.

Query strings are not part of the match key. An incoming query string is preserved and carried onto the target, so there is no point encoding one in from. If to already carries its own query string, the incoming one is appended to it with &.

Choosing a status

Status Meaning Use it when
301 Moved Permanently — transfers link equity The URL is retired for good. This is the default and the norm.
302 Found — temporary, may rewrite the request method The move is temporary and the method does not matter.
307 Temporary Redirect — temporary, preserves the method A temporary move that must keep a POST a POST.
308 Permanent Redirect — permanent, preserves the method A permanent move that must keep the request method.

Language Handling

A from is matched the way page paths are authored. A bare rule matches the plain path and every language-prefixed variant, and a path to inherits the language of the request — so one rule serves every locale and a French visitor lands on the French replacement, never the English one:

redirects:
  - from: /pricing
    to: /plans

That single rule answers /pricing, /en/pricing and /fr/pricing, sending each to /plans, /en/plans and /fr/plans respectively.

To target one locale only, write the language segment into from. A rule whose path already begins with a configured language code is matched literally:

redirects:
  - from: /fr/tarifs
    to: /fr/plans

An absolute to is used verbatim, with no language handling, since it leaves the app entirely.

Precedence

Redirects are evaluated after static assets and before pages:

  1. A real file in the public directory — a redirect rule can never hijack a served asset.
  2. Redirect rules.
  3. Page resolution.
  4. The 404 catch-all.

A rule therefore always beats a page. That cuts both ways: a from matching a path you still serve makes that page unreachable.

Validation

Three whole-table rules are enforced when the config is decoded, so a broken table fails sovrium validate instead of shipping:

  • No duplicate from — each path may declare at most one rule.
  • No self-redirect — a rule pointing at its own from loops forever.
  • No cycles/a → /b together with /b → /a is rejected. The server only ever resolves one hop, but the browser follows each new rule in turn and never settles.

Protocol-relative targets (//example.com) are also rejected. A browser resolves them as absolute cross-origin URLs, which would turn the redirect table into an open-redirect primitive; cross-origin hand-offs must spell out https:// so the intent is visible in review.

  • App Metadata — the other top-level identity properties.
  • Pages Overview — the page resolution that redirects run ahead of.
  • Languages — the configured language codes that drive prefix matching.
  • SEO & Metadata — canonical URLs, which a 301 should agree with.

Last updated July 27, 2026

This documentation was written with AI, so errors or outdated content are possible. Sovrium is in beta — contributions and corrections are welcome.

Built with Sovrium