Skip to content
AI-Readable Mode
Github.com

AI-Readable Mode

What it is

Void generates per-page Markdown mirrors, llms.txt, and llms-full.txt at build time so AI agents can consume your documentation as clean text. Every HTML page gets a <link rel="alternate" type="text/markdown"> tag pointing at its mirror, and a comment marker after <body>.

When to use it

The feature is on by default. If your docs are public and you want AI assistants (ChatGPT, Claude, Copilot, etc.) to index your content accurately, leave it enabled. If your docs are private or you don't want AI crawlers, disable it.

How it works

Per-page mirrors

For every Markdown source page, the plugin writes a .md file containing:

  1. A watermark header (site name, URL, build timestamp, version)
  2. The raw Markdown source (front matter stripped)
  3. A footer comment (<!-- End of markdown mirror. -->)

The mirror's path depends on url_style:

url_style Mirror path example Source path
"sidecar" (default) getting-started/installation.md getting-started/installation.md
"inline" getting-started/installation.md getting-started/installation/ directory

HTML decoration

Every built HTML page gets two additions:

<!-- before </head> -->
<link rel="alternate" type="text/markdown" href="getting-started/installation.md">

<!-- after <body> -->
<!-- void-ai-readable: getting-started/installation.md -->

llms.txt

Generated at the site root (llms.txt). Format:

# My Docs

getting-started/index.html  A quick start guide for new users.
getting-started/installation.html   How to install the theme.

Each line is <url>\t<description>. Descriptions resolve from: 1. ai_reader.description config override 2. page.meta.description front matter 3. page.title fallback

llms-full.txt

All mirrors concatenated into a single file (llms-full.txt), separated by --- (site) ---. This gives AI agents one file to read for the entire docs.

Sitemap

Mirror URLs are appended to sitemap.xml so crawlers discover them.

Configuration

theme:
  void:
    ai_reader:
      enabled: true                    # Master switch (default true)
      markup: true                     # Emit per-page .md mirrors (default true)
      url_style: "sidecar"            # "sidecar" | "inline" (default "sidecar")
      overwrite: false                 # Never clobber existing mirrors (default false)
      auto_title: true                 # Add # Title when source has no H1 (default true)
      exclude: []                      # Glob patterns to skip (e.g. "drafts/*.md")
      llms: true                       # Emit llms.txt (default true)
      llms_full: true                  # Emit llms-full.txt (default true)
      sitemap: true                    # Add mirrors to sitemap.xml (default true)
      description: ""                  # Override llms.txt description (default: from page)
      watermark:
        enabled: true                  # Emit watermark blocks (default true)
        header: true                   # Metadata at top of mirror (default true)
        footer: true                   # Closing comment at bottom (default true)
        text: "Generated by Void for AI agents."  # Marker line
        include_site: true             # Include site_name (default true)
        include_url: true              # Include canonical URL (default true)
        include_generated: true        # Include build timestamp (default true)
        include_version: true          # Include theme version (default true)

Exclude patterns

theme:
  void:
    ai_reader:
      exclude:
        - "drafts/*.md"
        - "internal/**/*.md"
        - "archive/*"

Patterns use Python fnmatch β€” * matches any characters, ** matches directories.

Custom llms.txt

To provide your own llms.txt, disable the auto-generated one and place your file in docs/:

theme:
  void:
    ai_reader:
      llms: false
      llms_full: false

Then add docs/llms.txt manually.

Under the hood

  • File: void/plugins/void_plugin.py
  • Defaults: _VOID_DEFAULT_AI_READER (line ~538)
  • Mirror generation: on_post_page() (line ~2953)
  • llms.txt/full + sitemap: on_post_build() (line ~3003)
  • HTML decoration: _ai_decorate_html() (line ~3132)
  • URL styles: _VOID_AI_READER_URL_STYLES (line ~874) β€” ("sidecar", "inline")
  • Validation: _validate_ai_reader() (line ~1372) β€” rejects unknown keys, invalid url_style, non-list exclude
  • Client-side: none β€” the entire feature is build-time only. The ai_reader config is injected into #__config but void.js never reads it.

Accessibility notes

  • The <link rel="alternate"> tag is in <head> β€” screen readers don't announce it, but AI tools and feed readers discover it automatically.
  • The <!-- void-ai-readable: ... --> comment is invisible to users.
  • The watermark header uses HTML comments β€” it doesn't affect the rendered page.