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 under /_llms/. 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 (no such route)
  /api/index: Broken link to /api/legacy (no such route)

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.