This documentation is also published as Markdown for efficient machine reading: the whole site is indexed at /llms.txt, and every page has a clean Markdown copy at the same URL with .md appended. These are generated from the same source and cost far fewer tokens to read than this rendered HTML.

Skip to main content Skip to navigation
Guides

Forward visitors from a renamed page

Set redirectUrl in front matter to forward visitors from the old path to the new one — an HTTP 301 on the live server, plus a meta-refresh stub in the static build.

When a published page is renamed or deleted, set redirectUrl: in its front matter to forward visitors to the new URL. On the dev and self-hosted server, Pennington issues a real HTTP 301 from the old path; the page body is not rendered or indexed. The static build also writes a <meta http-equiv="refresh"> stub at the old path, since a static host can't issue a server-side 301 without its own redirect config.

When the page is deleted rather than renamed, keep the file as a front-matter-only stub at the old path — title: and redirectUrl: with no body — so the old URL still resolves to a redirect. Delete the file and the old URL 404s.

redirectUrl: accepts an external absolute URL (https://…) as well as an internal path; the value is emitted verbatim as the 301 Location and the meta-refresh target, so a cross-site redirect works the same way.

For batch redirects across many paths, configure them at the hosting layer instead — Nginx or IIS rules (see Self-host behind Nginx or IIS) or a Netlify/Cloudflare/Azure rules file (see Adapt the deploy workflow for other hosts).

Before you begin

  • An existing Pennington site using AddDocSite (see Scaffold a documentation site with DocSite if not) or another host whose front-matter type implements IRedirectable. DocSiteFrontMatter and BlogSiteFrontMatter both do. For a custom record, add the interface — see The front-matter capability system.
  • Both the old URL (the page being retired) and the new URL (the canonical destination) are known.

To copy a working setup, see examples/DocSiteKitchenSinkExample, whose Content/main/redirect-source.md is a complete redirect page.

Add redirectUrl: to the old page

Open the markdown file at the old URL and set redirectUrl: to the new absolute path. Keep title: so diagnostics stay readable; the body does not render.

markdown
---
title: Old page URL
description: Redirects away to the new location.
redirectUrl: /main/front-matter/
order: 200
uid: kitchen-sink.main.redirect-source
---
  
A visit to this URL is intercepted by the Pennington redirect middleware
and returns HTTP 301 with a meta-refresh body pointing at `redirectUrl`.
The static build captures the same 301 and writes the meta-refresh file
to disk at this page's output path — one code path for dev and publish.

Verify

  • Run dotnet run and visit the old URL: the page redirects immediately to the target set in redirectUrl.
  • View source on the old URL: the markup contains <meta http-equiv="refresh" content="0;url=..."> and a <link rel="canonical" href="..."> pointing at the redirect target.
  • Check /sitemap.xml and /llms.txt: the old URL does not appear. A redirect has no canonical HTML page, so it is excluded from both.