Skip to content

REF-001 Broken links

Validates that relative links inside Markdown (links of the form [text](./file.md)) point to files that actually exist. If the target does not exist, an error is reported. Anchor fragments (#section) are excluded from the file existence check — their validity is the responsibility of REF-005 Anchors.

Renaming, deleting, or moving files is the most common way Markdown documents decay over time. AI-generated content can also introduce links to files that never existed. Broken links pass markdownlint and CI silently, so detecting them mechanically is essential.

FieldTypeRequiredDescription
excludestring[]Array of glob patterns whose link targets are excluded from validation
siteRouterobjectResolves routed URLs (e.g. /docs/x/) emitted by SSGs to real files

The rule works even with no options at all. Use exclude for cases where you intentionally link to documents or generated artifacts outside the include set.

By default REF-001 resolves relative links (./file.md) as file system paths. SSGs like Astro Starlight emit routed URLs (/docs/x/ or /ja/docs/x/) that don’t correspond to literal file paths, so without siteRouter they are flagged as broken.

Sub-fieldTypeRequiredDescription
presetstringKnown SSG preset. Currently "starlight" only
contentDirstringContent directory (e.g. "packages/site/src/content/docs")
defaultLocalestringDefault locale identifier. Use "root" for Starlight’s prefix-less root locale
localesstring[]Supported locale identifiers (e.g. ["root", "ja", "ko", "zh"])
urlPrefixstring(Generic, no preset) URL prefix to strip before resolving
indexFilestringIndex file name to try first (default: "index.md")

Starlight (i18n) example:

{
"rule": "ref001",
"options": {
"siteRouter": {
"preset": "starlight",
"contentDir": "packages/site/src/content/docs",
"defaultLocale": "root",
"locales": ["root", "ja", "ko", "zh"]
}
}
}

/docs/get-started/ resolves to <contentDir>/docs/get-started/index.md or <contentDir>/docs/get-started.md. /ja/docs/get-started/ resolves to <contentDir>/ja/docs/get-started/index.md.

Generic (no preset) example:

{
"rule": "ref001",
"options": {
"siteRouter": {
"contentDir": "src/pages",
"urlPrefix": "/wiki",
"indexFile": "README.md"
}
}
}

/wiki/some-page/ resolves to src/pages/some-page/README.md.

See [architecture](./architecture.md) for details.

If ./architecture.md does not exist, this triggers a violation.

docs/overview.md
line 1 error Link target "./architecture.md" does not exist REF-001
See [architecture](./architecture.md) for details.

Either create the target file architecture.md or update the link to the correct path.

{
"rule": "ref001",
"options": {
"exclude": ["generated/**/*.md"]
}
}