---
title: nuxt-llms-txt — Make your Nuxt site readable by AI
description: A Nuxt module that adds a Markdown mirror of every page plus a properly sectioned llms.txt index. Zero config, and it publishes your original Markdown source instead of a lossy HTML round-trip.
---

# Make your Nuxt site readable by AI

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.

```bash
npx nuxi module add nuxt-llms-txt
```

## What you get

Add one line to `nuxt.config.ts` and build the site. No route lists to
maintain, no frontmatter to add.

```ts
export default defineNuxtConfig({
  modules: ['nuxt-llms-txt'],
})
```

| Route | What it is |
| --- | --- |
| `/about.md` | A clean Markdown mirror of `/about`, with title and description frontmatter |
| `/about` + `Accept: text/markdown` | The same Markdown by content negotiation, served with `Vary: Accept` |
| `/llms.txt` | A sectioned index of the whole site, following the llmstxt.org convention |
| `/llms-full.txt` | Every page inlined into one file, for one-shot ingestion (opt in) |

Every HTML page also advertises its mirror with a
`<link rel="alternate" type="text/markdown">` tag and a matching `Link:`
response header — so agents find it without guessing.

## Source fidelity

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.

An HTML round-trip flattens the alert to a bare paragraph and drops the
language and file label from the fence. `nuxt-llms-txt` serves exactly what you
wrote in `content/`. Pages that *aren't* Markdown-backed fall back to HTML
conversion automatically, so a mixed site works either way.

## The index

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.

- **Descriptions are real.** Pulled from `useSeoMeta`, `og:description` or
  frontmatter, falling back to the first substantial paragraph.
- **Chrome is stripped.** `nav`, `header`, `footer`, `aside` and anything
  marked `data-ai-ignore` never make it in.
- **Override anything.** Declare your own sections, mark routes as `Optional`,
  or reshape the corpus in a build hook.

## Details

- **Static or SSR, both.** Files are written during prerendering, so
  `nuxi generate` needs no server. A Nitro middleware covers SSR-only routes on
  demand.
- **Content negotiation.** Markdown is served from the HTML route only when the
  client explicitly asks. `*/*` deliberately still gets HTML, so ordinary API
  consumers never break.
- **Per-locale indexes.** With `@nuxtjs/i18n`, each locale gets its own
  `/{locale}/llms.txt`.
- **AI descriptions, opt in.** 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.
- **Build hooks.** `llms-txt:pages` to mutate the corpus, `llms-txt:files` to
  add, edit or drop outputs just before they are written.
- **Usable without Nuxt.** The conversion and index machinery ships separately
  as `nuxt-llms-txt/core`.

## Comparison

| | `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` | ✅ | ❌ | ✅ |

## Links

- [Full documentation](https://github.com/ovion-dev/nuxt-llms-txt#readme)
- [GitHub](https://github.com/ovion-dev/nuxt-llms-txt)
- [npm](https://npmjs.com/package/nuxt-llms-txt)
- [llmstxt.org](https://llmstxt.org)

MIT © Ovion
