A Markdown mirror of every page, plus a properly sectioned llms.txt index. Zero config — and it publishes your original Markdown, not a lossy HTML round-trip.
MIT licensed · no runtime dependencies added to your bundle · works with nuxi generate and SSR
No route lists to maintain, no frontmatter to add. The module discovers your pages during prerendering and writes everything itself.
export default defineNuxtConfig({ modules: ['nuxt-llms-txt'], })
A clean Markdown mirror of /about, with title and description frontmatter.
The same Markdown by content negotiation, served with Vary: Accept.
A sectioned index of the whole site, following the llmstxt.org convention.
Every page inlined into one file, for one-shot ingestion by a model.
<link rel="alternate" type="text/markdown"> tag and a matching Link: response header — so agents find it without guessing.
If a page came from a Markdown file, that file's Markdown is what gets served — MDC components, fence labels, tables and all. Converting rendered HTML back to Markdown throws every one of those away.
Keep your key on the server. ``` npm install @acme/sdk ``` // the alert became a bare paragraph // the language and file label are gone
::alert{type="warning"} Keep your key on the server. :: ```bash [npm] npm install @acme/sdk ``` // exactly what you wrote in content/
@nuxt/content.
Sections come from your route tree. A top-level segment only becomes its own heading once it has children — so a flat marketing site gets one clean list, and a docs site gets real sections.
useSeoMeta, og:description or frontmatter, falling back to the first substantial paragraph.
nav, header, footer, aside and anything marked data-ai-ignore never make it in.
Optional, or reshape the corpus in a build hook.
# Acme Inc > Acme builds tools for building tools. ## Pages - [Acme Inc](https://acme.test/index.md): Acme builds developer tools that get out of your way. - [Pricing](https://acme.test/pricing.md): Simple, transparent pricing for teams of every size. ## Docs - [Documentation](https://acme.test/docs.md): Guides, API reference and recipes. - [Getting started](https://acme.test/docs/getting-started.md): Install the SDK and make your first request. ## Optional - [Terms of service](https://acme.test/legal/terms.md): The legal agreement between you and Acme Inc.
Files are written during prerendering, so nuxi generate needs no server. A Nitro middleware covers SSR-only routes on demand.
Markdown is served from the HTML route only when the client explicitly asks. */* deliberately still gets HTML, so ordinary API consumers never break.
With @nuxtjs/i18n, each locale gets its own /{locale}/llms.txt. Prefixes are stripped before sections are derived, so /fr/docs lands under Docs.
Pages missing a description can have one written at build time. No key means no calls, results are cached by content hash, and a failure never fails your build.
llms-txt:pages to mutate the corpus, llms-txt:files to add, edit or drop outputs just before they're written.
The conversion and index machinery ships separately as nuxt-llms-txt/core — framework-free, for scripts, CI checks or another adapter.
There are two existing options in the Nuxt ecosystem, and neither does the whole job.
| nuxt-llms-txt | nuxt-llms | @mdream/nuxt | |
|---|---|---|---|
llms.txt | ✓ | ✓ | ✓ |
Per-page .md mirrors | ✓ | — | ✓ |
| Routes discovered automatically | ✓ | hand-written | ✓ |
| Publishes your original Markdown | ✓ | n/a | HTML round-trip |
| Sectioned index with real descriptions | ✓ | manual | flat list |
Per-locale llms.txt | ✓ | — | — |
Works without @nuxt/content | ✓ | — | ✓ |
llmsTxt: { // Inferred from site.url when omitted. domain: 'https://example.com', title: 'Example', description: 'What this site is.', // exclude is merged with the built-in defaults. include: ['/**'], optional: ['/legal/**'], // Override the derived sections entirely. sections: [ { title: 'Documentation', match: '/docs/**' }, { title: 'Blog', match: '/blog/**' }, ], markdownFiles: true, // write /foo.md full: false, // also emit /llms-full.txt negotiate: true, // honour Accept: text/markdown source: true, // prefer original Markdown }
The defaults are chosen so that the common case — a Nuxt site that wants to be legible to models — needs nothing but the module name. Reach for config when you want to change the shape of the index, not to make it work.
NuxtConfig, so every option is autocompleted and checked.
/api/**, /_**, /200 and /404 are excluded by default and stay excluded when you add your own.
noindex is respected. Pages you keep out of search stay out of the index and the mirrors too.
Then check /llms.txt.