Link validation
Opt-inValidate internal links and anchor fragments at build time to catch broken references before they reach production.
The linkValidation feature walks every <a href> and <img src> in the build and validates that internal links and anchor fragments resolve correctly. Broken links produce build diagnostics — warnings by default, errors when failOnBroken: true is set.
External URLs (http:, https:, mailto:, etc.) are silently skipped by default.
Enable
// zfb.config.ts
export default defineConfig({
markdown: {
features: {
linkValidation: {}, // defaults: warn-only, skip external URLs
},
},
});To make broken links fail the build:
linkValidation: { failOnBroken: true },What is validated
Bare anchor fragments —
#section-idmust match a heading ID in the current file.File links without anchor —
.must resolve to an existing file under the project root./ other. md File links with anchor —
.requires both a resolvable file and a matching heading ID in that file./ other. md# section- id
Heading IDs come from HeadingLinksPlugin, which runs earlier in the same hast phase. The cross-file heading-ID registry is populated during the build so anchor validation works across files. Headings that arrive via transclusion are included in the registry, so . validates correctly.
What is skipped
External URLs starting with
http:,/ / https:,/ / mailto:, ortel:.Links in files rendered without a
BuildContext(e.g. simple in-memory pipeline calls without context).Cross-file anchor links whose target file is outside the bundler's walked directories (pages, content collections, components, layouts). These degrade to existence-only validation: the file must exist on disk, but the fragment is not checked. If the target file IS in the build, the fragment is always verified.
Options
failOnBroken— whentrue, broken links emitErrordiagnostics (build fails). Default:false(warnings only).
Diagnostic format
Diagnostics follow the shared BrokenLink variant in MarkdownDiagnostic:
severity—WarningorErrordepending onfailOnBroken.url— the raw href or src value as written by the author.location.path— absolute path of the source file containing the broken link.
Behavior change in #980
Before #980, cross-file anchor fragments (.) were validated only for existence — the fragment itself was not checked against the target file's headings. Starting with #980, the fragment is verified post-compile for every file in the build. Builds that previously passed with a broken cross-file anchor under failOnBroken: true will now fail.
Phase
Runs in two phases:
Per-compile hast phase —
LinkValidationPluginvalidates same-file anchors (#section-id) immediately and records cross-file fragment candidates for post-compile resolution.Post-compile bundler pass — after all files have been compiled, the bundler assembles a heading map from every file's recorded headings and verifies each recorded cross-file candidate. Findings are routed through the same severity gate as other markdown diagnostics.