Skip to content

vitepress-plugin-llms

Публикует LLM-совместимые артефакты для сайта VitePress: индекс llmstxt.org (/llms.txt), полнотекстовый дамп всех страниц одним файлом (/llms-full.txt) и зеркало каждой страницы в исходном Markdown (<url>.md). Инструмент, который скачивает /foo/index.md, получает исходник, а не HTML-обёртку VitePress.

Полезно, когда документацию хотят видеть роботы поисковой выдачи (GEO), ассистенты вроде ChatGPT/Claude и внутренние RAG-пайплайны -- HTML-рендер VitePress для них избыточен и шумит вёрсткой.

Установка

bash
pnpm add @ampernic/vitepress-plugin-llms

Если пакет ставится из Forgejo, а не из npmjs, дополнительно пропишите скоуп в .npmrc:

@ampernic:registry=https://altlinux.space/api/packages/ampernic/npm/

Использование

Плагин возвращает три хука VitePress-конфига -- их надо разложить в корень defineConfig:

ts
// .vitepress/config.ts
import { defineConfig } from 'vitepress'
import { LlmsPlugin } from '@ampernic/vitepress-plugin-llms'

const llms = LlmsPlugin({
  hostname: 'https://docs.altlinux.space',
  title: 'ALT Linux Documentation',
  description: 'Справочная документация по дистрибутивам ALT.',
  section: (p) => p.url.split('/').filter(Boolean)[0] ?? 'root',
  filter: (p) => !p.url.endsWith('/404.html'),
})

export default defineConfig({
  transformPageData: llms.transformPageData,
  buildEnd: llms.buildEnd,
  vite: llms.vite,
})

Через createSharedConfig темы @ampernic/vitepress-theme-alt-docs эти хуки пробрасываются автоматически -- опции передаются полем llms.

В dev-режиме vite.plugins добавляет middleware, отдающий .md с Content-Type: text/markdown; charset=utf-8, чтобы браузер и внешние клиенты не ошибались на MIME.

Опции

ОпцияТипПо умолчаниюОписание
hostnamestring--Абсолютный origin для полей absoluteUrl в llms.txt / llms-full.txt. Без него URL остаются root-relative
titlestring'Documentation'Заголовок llms.txt и llms-full.txt. По умолчанию берётся из frontmatter корневой страницы (altHome.hero.title или title)
descriptionstring''Однострочное описание сразу под заголовком. Фолбэк тоже из корневого frontmatter
fallbackSummarystring''Подпись пункта в llms.txt, если у страницы нет первого абзаца
emitIndexbooleantrueПисать llms.txt
emitFullTextbooleantrueПисать llms-full.txt
emitPerPageMarkdownbooleantrueДля каждой страницы класть зеркало <url>.md рядом с HTML
filter(page: PageMeta) => boolean--Отсекает страницы (автогенерированные индексы, редиректы) от всех артефактов
section(page: PageMeta) => stringпервый сегмент URLКлюч группировки в дереве llms.txt
pageTitle(page: PageMeta) => stringfrontmatter title | pageData.titleПере-именовывает пункт в индексе
summary(page: PageMeta) => stringпервый абзац источникаОднострочник страницы в llms.txt
renderSource(page: PageMeta) => string | undefined--Переписывает то, что попадает в артефакты и per-page .md. Нужно, чтобы разложить frontmatter-driven лэндинги (<DocSections />) в реальный Markdown для LLM
fullTextMaxBytesnumber8 * 1024 * 1024Жёсткий предел размера llms-full.txt. Старые LLM-клиенты давятся многомегабайтными файлами. 0 -- без ограничения
preamblestring--Дополнительный Markdown-блок в шапке llms.txt -- контакты, лицензия, описание проекта
extraPages() => SyntheticPage[]--Синтетические страницы, дописываемые в набор перед emit. Пригодится сайту-агрегатору, который сам страницы не хостит, но перечисляет их

Что попадает в артефакты

  • llms.txt: заголовок + описание + опциональный preamble + плоский список бессекционных элементов + сгруппированные по section(page) пункты со ссылками и однострочником каждой страницы.
  • llms-full.txt: заголовок + описание + один блок на страницу, разделитель ---, шапка url: / title:. Порядок -- лексикографический по URL, чтобы разница между сборками была детерминированной.
  • Per-page .md: сырой Markdown из репозитория. При <url>/ VitePress отдаёт <url>index.md, при <url> -- <url>.md.

Нюансы вывода

  • renderSource вызывается до filter. Если корневой лэндинг рендерится из frontmatter, вернуть из него полноценный Markdown -- единственный способ показать его LLM осмысленно.
  • Заголовок и описание llms.txt резолвятся так: параметры плагина > altHome.hero.title / altHome.hero.text корневой страницы > её title / description > дефолты. На перстрановом сайте "корень" -- это ${base} (например, /alt-workstation/), а не /.
  • При hostname не задан URL пунктов -- root-relative. Индексаторы GEO часто требуют абсолютные ссылки, лучше задавать всегда.
  • Per-page .md пишется в outDir без префикса site.base: при деплое дистрибутив уже лежит под /<distro>/, повторный префикс дал бы 404.