Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mdgate

A CI gate for the markdown twin of your docs site.

Many docs sites now publish a machine edition alongside the HTML: a .md twin for every page and an llms.txt index, so AI agents can read the docs as plain text. The twin is generated from the same source as the HTML, and usually nothing reads it in CI. When the generator drops something, the HTML stays perfect and the text edition silently loses content. No person opens the .md files. The only reader who hits the bug is a machine, and machines do not file bug reports.

mdgate crawls your llms.txt and asserts three things:

  1. No empty blocks. A code fence or multilang block that renders five install commands in HTML should not come out as six blank lines in the .md.
  2. No unresolved values. If the .md says "created with up to key columns" and the rendered page says "up to 4 key columns", a value component was stripped. mdgate finds the gap, then confirms it against the rendered page and reports the value the HTML shows.
  3. The text path of every internal doc link resolves. mdgate checks the .md side of every internal link and, when it fails, fetches the page side to name the exact failure. The sharpest case: redirects live in the web app's route layer, and static .md files never see them. A person following a stale link gets redirected; an agent following the same link with .md gets a 404, even when the content exists at the new path.

Exit codes: 0 clean, 1 findings, 2 the index itself could not be read. Transient trouble (network errors, 429, 5xx) is reported as a warning, and warnings never fail the build. Only a 404 or 410 proves a twin is missing.

Usage

No dependencies. Python 3.10+.

python3 mdgate.py https://example.com
python3 mdgate.py https://example.com --index /llms.txt --delay 0.15 --json

--max-pages caps the scan (default 200 indexed pages).

Example output:

https://example.com/docs/index.md
  x line 63    broken-link      https://example.com/docs/old-name.md is 404. A person is redirected https://example.com/docs/old-name -> https://example.com/docs/new-name and https://example.com/docs/new-name.md exists. The redirect lives only in the HTML route layer; the text path dead-ends

https://example.com/docs/quickstart.md
  x line 26    empty-block      empty multilang block

https://example.com/docs/write.md
  x line 616   unresolved-value gap in 'An index can be created with up to  key columns.'; the rendered page shows '4' here

41 pages scanned, 86 links checked: 3 failures, 0 warnings

In CI

# .github/workflows/docs-text-path.yml
name: docs text path
on:
  schedule:
    - cron: "0 6 * * *"
  workflow_dispatch:
jobs:
  mdgate:
    runs-on: ubuntu-latest
    steps:
      - run: curl -fsSLO https://raw.githubusercontent.com/yylerbrown/mdgate/main/mdgate.py
      - run: python3 mdgate.py https://your-site.com

A scheduled run like this catches a lossy conversion within a day. To block the merge that introduces one, run the same command against your deploy preview URL in the docs repo's pull-request pipeline (or vendor mdgate.py into that repo).

Tests

python3 -m unittest test_mdgate -v

Limitations

  • Anchors (#fragment) are not checked.
  • Only inline [text](target) links are checked. Reference-style links, autolinks, and raw HTML <a> tags are skipped. Links inside code blocks are deliberately ignored, and so are images and other assets (.png, .json, ...), which have no .md twin.
  • The unresolved-value check is a heuristic (mid-sentence double spaces, confirmed against the rendered page). A stripped value that leaves no gap at all is invisible to it.
  • The multilang half of check 1 matches the <!-- multilang --> comment convention. Sites that mark tabbed code groups differently need a one-line pattern tweak.
  • Only links under the indexed docs prefixes are checked, and only on the same host.
  • Requests are rate limited (--delay, default 0.15s) and sent with an identifying user agent. Be polite: run it against your own site, or keep the delay generous.

License

MIT

About

A CI gate for the markdown twin of your docs site

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages