zudo-doc
GitHub repository

Type to search...

to open search from anywhere

Link Checker

Created Mar 26, 2026Updated Jun 7, 2026Takeshi Takatsudo

Post-build broken link checker that validates internal links in built HTML and MDX source files.

Link Checker

zudo-doc includes a built-in link checker (scripts/check-links.js) that runs two types of validation after the site is built.

What It Checks

Mode 1: Built HTML scan

Scans all .html files in dist/ for internal <a href="..."> links and verifies each target exists on disk. It handles:

  • Base path stripping (e.g., /my-docs/docs/foodocs/foo)

  • Trailing slash resolution (docs/foo/docs/foo/index.html)

  • Extension resolution (docs/foodocs/foo/index.html or docs/foo.html)

  • Query string and fragment stripping before resolution

  • Relative link resolution against the file's directory

  • Caching resolved paths for performance

Links that are skipped (not checked):

  • External URLs (https://, http://)

  • Anchor-only links (#section)

  • mailto:, javascript:, data:, tel: URIs

  • Versioned docs links (/v/*/) — version content may be incomplete

Mode 2: MDX source scan

Scans all .mdx and .md files in the configured content directories for absolute links that bypass the base path. This catches links like:

<!-- These are flagged — they bypass the base path -->
[guide](/docs/guides/foo)
<a href="/ja/docs/guides/foo">link</a>

<!-- These are fine — they use relative paths -->
[guide](./foo.mdx)
[guide](../other/bar.mdx)

When a base path is configured (e.g., /my-docs/), absolute links starting with /docs/ or /ja/docs/ will break because they're missing the base path prefix. The MDX source scan catches these before they become broken links in production.

Links inside fenced code blocks are ignored.

Build the site first, then run the checker:

pnpm build && pnpm check:links

By default, the checker exits with code 0 even when issues are found (non-strict mode). Use --strict to fail on issues:

pnpm check:links --strict

The link checker runs as step 10 of 13 in the pre-push validation (pnpm b4push):

  1. Format check (mdx)

  2. Template drift check

  3. Pin parity check

  4. Fixture settings drift check

  5. Tags audit (--ci)

  6. Design token lint

  7. Type checking

  8. Root unit tests

  9. Build

  10. Link check

  11. HTML validation

  12. Automated preview smoke (blocking)

  13. Manual interactive smoke (operator-driven)

The canonical, authoritative b4push step list lives in the header comment of scripts/run-b4push.sh — treat that script as the single source of truth. The list above is a summary; if it ever drifts, the script wins.

The link checker runs in the build-site job of the PR checks workflow (pr-checks.yml), immediately after pnpm build.

Output

When no issues are found:

Checking links (base: /my-docs/)...

✓ No broken links or absolute path issues found

When issues are found:

Checking links (base: /my-docs/)...

=== Broken Links in Built HTML ===
  dist/docs/page/index.html:42  /my-docs/docs/missing-page

=== Absolute Links Bypassing Base Path (MDX Source) ===
  src/content/docs/guides/test.mdx:15  /docs/guides/foo

✗ Found 1 broken link and 1 absolute path warning

Each entry shows the file path, line number, and the problematic href.

Configuration

The link checker reads its configuration from src/config/settings.ts:

  • base — The site's base path, used to strip prefixes when resolving links

  • docsDir — Primary content directory for MDX source scanning

  • locales — Locale configurations with dir fields pointing to additional content directories for MDX source scanning (e.g., locales: { ja: { dir: "src/content/docs-ja" } })

Revision History

Takeshi TakatsudoCreated: 2026-03-26T23:19:35+09:00Updated: 2026-06-07T17:11:47+09:00

AI Assistant

Ask a question about the documentation.