How to Add llms.txt to VitePress
VitePress is the Vue-powered static site generator behind the documentation
of Vite, Vue.js, Vitest and many other flagship open-source projects. It has
no native llms.txt feature — yet its own documentation ships one,
and so do the docs of every major project in its ecosystem. Two routes get you
there: a static file in public/, or build-time generation with
vitepress-plugin-llms. Both are covered here, with real config and
a curl check.
VitePress Docs Sites That Already Publish llms.txt
Documentation is where llms.txt earns its keep — the llmstxt.org spec notes that coding agents follow the file to reach API references and tutorials — and the VitePress ecosystem was among the first to dogfood it. These are not hypothetical examples. Verified with curl on 2026-09-06:
| Site | Built with VitePress for | /llms.txt on 2026-09-06 |
|---|---|---|
| vuejs.org | Vue.js | HTTP 200 |
| vite.dev | Vite | HTTP 200 |
| vitest.dev | Vitest | HTTP 200 |
| vitepress.dev | VitePress itself | HTTP 200 |
The shape of these files is worth studying. The one on vitepress.dev starts with a single H1, a one-line blockquote summary, and a Table of Contents:
# VitePress
> Vite & Vue Powered Static Site Generator
Markdown to beautiful docs in minutes
## Table of Contents
- [Getting Started](/guide/getting-started.md): Get up and running with VitePress.
Learn how to install, scaffold, and start developing your documentation site.
- [Asset Handling](/guide/asset-handling.md): Learn how to reference and handle
static assets such as images, media, and fonts in VitePress.
Notice the links: every page is listed as a .md URL. That is the
markdown page form the llms.txt
v2 spec defines — a VitePress page rendered as clean Markdown is exactly
the format an LLM wants to ingest, and it is what
vitepress-plugin-llms outputs.
Method 1: Drop a Static File in the public Directory
VitePress gives you a shortcut that most SSGs do: everything in the
public directory — docs/public by default, directly
under your source directory — is copied verbatim to the root of the build
output. The official docs name robots.txt and favicons as the
typical use case; llms.txt works the same way. Create
docs/public/llms.txt:
# Acme Docs
> Acme Docs is the official documentation for the Acme platform.
> It covers installation, configuration and the REST API.
## Getting Started
- [Quickstart](https://docs.example.com/getting-started/): first project in five minutes
- [Authentication](https://docs.example.com/authentication/): API keys and scopes
## API Reference
- [REST API](https://docs.example.com/api/): every endpoint, parameter and error
The next npm run docs:build serves it at
https://docs.example.com/llms.txt. Two notes: if you set a custom
srcDir, the public directory follows it, and if the site deploys
under a subpath via the base option, the file still lands at the
output root while your listed URLs stay absolute. This route is fine while
your docs are small and stable — the cost is that every new page means a hand
edit, and a file that drifts from your content is a file agents follow into
stale territory.
Method 2: Auto-Generate with vitepress-plugin-llms
The ecosystem workhorse is okineadev/vitepress-plugin-llms — roughly 400 stars as of September 2026, and adopted across the VoidZero ecosystem with the blessing of Vue.js. The flagship sites above use it: the file served on vitepress.dev is its output. Install and register it:
# terminal
npm install vitepress-plugin-llms --save-dev // .vitepress/config.ts
import { defineConfig } from 'vitepress'
import llmstxt from 'vitepress-plugin-llms'
export default defineConfig({
vite: {
plugins: [llmstxt()],
},
})
Zero configuration required. Every build now writes three things into
.vitepress/dist: llms.txt (the curated index with
section links), llms-full.txt (all documentation merged into one
file — see how the two relate in the
llms.txt vs
llms-full.txt guide), and a clean Markdown version of every page, which
llms.txt links to. The plugin authors call out one practice that visibly
improves the output: add a description to each page's frontmatter
and it becomes the link description in llms.txt — which is exactly what an
agent reads when deciding which link to fetch.
Two finer points from the project's documentation. First, you can mark
sections of a Markdown source file as llm-only or
llm-exclude to control what reaches the LLM versions — useful for
instructions aimed at agents, or human-only notes. Second, for repositories
with documentation in multiple languages the author recommends enabling the
plugin for the English docs only; that is all an LLM needs.
Alternative: vitepress-plugin-llmstxt
If you need finer control than zero-config gives you,
vitepress-plugin-llmstxt
(npm 0.5.x, zero dependencies) also generates llms.txt,
llms-full.txt and per-page Markdown files, then adds: glob-based
ignore patterns to exclude routes, a transform
callback that rewrites generated content, dynamic-route and i18n support, and
experimental compatibility with VitePress 2.0 alpha. A configured example:
// .vitepress/config.ts
import { defineConfig } from 'vitepress'
import llmstxt from 'vitepress-plugin-llmstxt'
export default defineConfig({
vite: {
plugins: [
llmstxt({
hostname: 'https://docs.example.com',
ignore: ['**/api/**/*'],
}),
],
},
})
The hostname option pins the absolute URLs in your file (useful
when VitePress infers the wrong origin), and ignore keeps
internal or generated pages out of the index.
Static File or Plugin?
| Approach | Setup | Per-page .md | llms-full.txt | Stays current |
|---|---|---|---|---|
Static docs/public/llms.txt | 1 minute | No | No | Manual edits only |
vitepress-plugin-llms | ~5 minutes | Yes | Yes | Every build |
vitepress-plugin-llmstxt | ~5 minutes | Yes | Yes | Every build |
A hand-written file is fine while your sitemap is small and your structure rarely moves. The moment docs change weekly — new guides, migrated pages, added API endpoints — generation wins, because the llms.txt an agent reads is only as trustworthy as its last update, and a plugin cannot forget to update itself.
The VitePress Checklist
- Confirm the public directory path — it is
docs/publicby default but moves withsrcDir; a static file in the wrong folder quietly never gets published. - Register the plugin under
vite.plugins, not at the top level of the VitePress config — these are Vite plugins and VitePress only loads them there. - Write a
descriptionin every page's frontmatter — it becomes the link description agents use to choose pages. "What problem this page solves" beats a module name. - Keep it English-only for LLM purposes — for multi-language docs, generate the file from the English tree only, per the plugin's own guidance.
- Verify the deployed file, not just the build — redirect rules, domain moves and docs restructures break llms.txt in production after the build goes green. Confirm it serves as plain text:
curl -s -o /dev/null -w "%{http_code} %{content_type}\n" https://docs.example.com/llms.txt
# Expect: 200 text/plain Then paste the URL into the free llms.txt checker to validate the H1, blockquote summary, absolute URLs and section structure against the spec. To draft the initial file in seconds, feed your docs sitemap into the free llms.txt generator, then let the plugin keep it current from there. VitePress made llms.txt a zero-maintenance default for the biggest projects in the Vue ecosystem — your docs can be next.