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

April 6, 2026

A build report you can read, and a dev overlay that shows it

By Phil Scott

Pennington used to scatter its findings — a broken link, an xref: that points nowhere, a content diagnostic — across logger output, where they slipped past unnoticed. Two changes make them easier to catch: the static build now ends with a report, and the dev server shows the same findings while you write.

A report at the end of every build

Run dotnet run -- build and the last thing you see is a structured summary along these lines:

text
Build Complete — 142 pages in 1.2s
  142 pages generated
  3 warnings
  
WARNINGS
  /guide/migration: Unresolved xref: reference.api.old-name
  /guide/setup: Broken link to /guide/instalation (Page not found)
  /api/index: Broken link to /api/legacy (Page not found)

When the report finds errors, the process exits with code 1, so a broken link fails a CI pipeline instead of slipping through. The build verifies internal links against the real route table and resolves every xref: against the cross-reference UID index as it goes.

The same warnings, live in the browser

Catching problems at build time is useful; catching them while you're still typing is better. In dev mode, Pennington collects diagnostics per request — so every warning is tied to the page that produced it — and shows them in a floating overlay in the browser.

Edit a page, introduce a bad link, and the overlay updates on the next reload. The diagnostics also travel in HTTP headers and the SPA navigation payload, so they survive client-side page transitions. The request-scoped diagnostics reference covers how that works.