Overview
The redirect system handles URL changes through two layers:
- Global manifest — site-wide redirect rules defined in
src/site/config/redirects.ts - Content-level redirects — per-entry
redirectFromfrontmatter inpagesandarticles
Both sources are merged at build time into Astro’s native redirect routing. Redirects execute at the server level via the Node adapter (REQ-00132).
Who this is for
- Developers configuring global redirect rules or troubleshooting redirect conflicts
- Editors adding
redirectFromfrontmatter to preserve old URLs after content moves
Global Manifest (REQ-00173)
The manifest follows the core-schema / site-instance pattern:
- Schema:
src/core/config/redirects.schema.ts(CORE-OWNED) — defines theRedirectRuletype - Instance:
src/site/config/redirects.ts(SITE-OWNED) — site-specific rules
Each rule specifies a source path, destination, and HTTP status code:
import type { RedirectRule } from "@core/config/redirects.schema";
export const redirects: RedirectRule[] = [
{ from: "/old-page/", to: "/new-page/", status: 301 },
{ from: "/promo/", to: "/services/", status: 302 },
{ from: "/legacy/", to: "https://example.com/new/", status: 301 },
];
Source path rules
- Must start with
/(absolute path) - Must not contain query parameters
- Trailing slash is auto-normalized (added if missing)
Destination values
- Site-internal: absolute path (e.g.,
/new-page/) - External: full URL (e.g.,
https://example.com/new/)
Status codes
301— permanent redirect (use for URL changes, slug renames)302— temporary redirect (use for seasonal or time-limited redirections)
Content-Level Redirects (REQ-00174)
Content entries in pages and articles can declare old URLs using the redirectFrom frontmatter field:
---
title: Our Services
description: What we offer.
redirectFrom:
- /old-services/
- /what-we-do/
---
Each path in the array becomes a 301 redirect pointing to the entry’s canonical URL. The canonical URL is derived from the entry’s collection and slug — or from linkedRoute if present.
Path format
Same rules as the manifest: must start with /, no query parameters, trailing slash auto-normalized.
Query Parameter Passthrough
When a request hits a redirect source path with query parameters, those parameters are preserved in the redirect destination. For example:
- Request:
/old-page/?ref=campaign→ Redirect:/new-page/?ref=campaign
If the destination already includes its own query parameters, the destination’s parameters are used instead of the incoming ones.
Conflict Handling
Manifest-internal duplicates
If the manifest contains two rules with the same source path, the build fails with an error identifying the duplicate.
Frontmatter duplicates
If two content entries both claim the same redirectFrom path, the build fails with an error identifying both entries.
Frontmatter–manifest conflict
If a frontmatter redirectFrom path matches a manifest rule for the same source path, the frontmatter wins. A build warning is emitted so the manifest author is aware of the override.
Node Adapter Requirement
Redirects require a server adapter (@astrojs/node or equivalent) to produce HTTP redirect responses. The Astro Node adapter serves redirect routes with HTTP 308 status (semantically equivalent to 301 for GET requests). This is an Astro framework behavior — the configured status code in the manifest is preserved for provider-specific output generation if added in the future.
Build-Time Validation
The lint:content-ingestion script validates redirectFrom entries for:
- Path format (leading slash, no query parameters)
- Duplicate source paths across content entries
- Conflicts with manifest rules (warning)
This runs as part of npm run validate, providing early feedback before the full Astro build.
Provider-Specific Output (Future)
The current implementation handles redirects at runtime via middleware and Astro’s native redirect config. Provider-specific output file generation (e.g., Netlify _redirects, Vercel vercel.json, Cloudflare _redirects) is a documented extension point for future work (REQ-00173).