Skip to content

Redirects

Real redirects, compiled — not a client-side hack.

json
{
"redirects": [
{ "source": "/old-guide", "destination": "/guides/getting-started" },
{ "source": "/legacy", "destination": "https://example.com/elsewhere", "permanent": false }
]
}
sourcestringrequired

Site-root-relative path, without the base prefix — Reed adds it.

destinationstringrequired

Site-root-relative path, or an absolute http(s) URL.

permanentbooleandefault: true

true emits a 301, false a 302.

These compile into actual redirects in the built output, with an explicit status code — not a meta-refresh and not a client-side script. A crawler following one gets the status you asked for.

permanent defaults to true. Think before accepting it: a 301 is cached aggressively by browsers and intermediaries, and undoing one in the field is genuinely hard. Use false while a move is still provisional.

Two entries whose source normalizes to the same path is a schema error. Previously this was a silent last-one-wins, which is the kind of behaviour that makes a redirect table impossible to reason about as it grows. Now the config simply refuses to build.

source and destination follow the docs.json rule: root-relative values are base-prefixed by Reed. So on a site with base: "/docs", a source of /old-guide matches the served URL /docs/old-guide.

This is the opposite of what you write in page prose, where you supply the prefix yourself. If you find yourself writing /docs/... in a redirect, you have almost certainly produced /docs/docs/....

There is no pattern matching, no wildcard, and no capture-group substitution — each entry is one exact path to one destination. Moving a whole subtree means one entry per page.

That is a real limitation. When the list gets long enough to be painful, the alternative is a rule at your host or CDN layer, which is outside Reed and stays outside it.