Validate
blume validate checks every link in your content — pages, anchors, assets, and optionally external URLs — and fails CI when one is broken.
blume validate reads your content the way a build does and checks every link it finds. It doesn’t generate or build anything, so it’s the fast gate to put in front of blume build:
blume validate
- Internal page links (
/guides/intro,./sibling) must resolve to a real page — broken ones are reported as errors. A component’s stringhref(<Card href="./install">) is checked the same way; anhref={…}expression isn’t. - Anchor links (
#section,/guides/intro#setup) must match an anchor on the target page — a heading’s id (generated or pinned) or a raw HTML element’sidattribute — with misses reported as warnings. Ids inside code blocks, inline code, HTML comments, and<Prompt>blocks don’t count. - Asset links are checked where the file lives: an absolute path (
/logo.png) against thepublic/directory, a relative image embed () against the page’s own folder. A plain link to a relative path still resolves as a site route — only image embeds go through the image pipeline. - External links are only checked with
--external(off by default since it requires the network); dead links (404/410/unreachable) are errors, while rate-limited or transient responses (403/429/5xx/timeout) are warnings.
What counts as a page
Links resolve against everything the built site serves, not just Markdown pages: custom .astro pages, the generated changelog index, every configured redirect, and, on a multi-language site, an untranslated page’s fallback URL under each locale. A page that fails to parse is reported alongside the link findings, because a page that never loads is a link-validation blind spot rather than a clean result.
Flags
--external— also check externalhttp(s)links over the network.--strict— exit non-zero on warnings too. Info-level notes stay advisory.--json— emit the diagnostics as JSON on stdout instead of the terminal report.
Diagnostics
| Code | Severity | Meaning |
|---|---|---|
BLUME_BROKEN_LINK |
error | An internal link points at a route no page serves. |
BLUME_BROKEN_ANCHOR |
warning | The page exists but has no anchor matching the fragment. |
BLUME_BROKEN_ASSET |
warning | An absolute path isn’t in public/, or a relative image embed isn’t beside the page. |
BLUME_ASSETS_UNCHECKED |
info | There is no public/ directory, so absolute asset paths weren’t checked. |
BLUME_DEAD_LINK |
error or warning | An external link (with --external) returned 404/410 or was unreachable (error), or a transient 403/429/5xx/timeout (warning). |
The exit code is the contract: errors exit non-zero, and --strict makes warnings do the same.
JSON output
With --json, blume validate (and blume doctor) write one object to stdout: a diagnostics list, each entry carrying its code, severity, message, the file relative to the project root with line and column when the finding has a location, a suggestion, and a docsUrl pointing at the page that explains the code, plus a summary of counts per severity. The exit code is unchanged, so the same invocation gates CI and feeds an editor integration.