Core Concepts

llms.txt Generation

Last updated by Harlan Wilton in doc: clarify usage for llms.txt.

Nuxt AI Ready generates /llms.txt and /llms-full.txt during prerender following the llms.txt standard.

/llms.txt

Site overview with page links. Built from page metadata collected during prerender.

Live example: nuxtseo.com/llms.txt

# <Site Title>

> <Site Description>

## Pages

- [Page Title](/page-link): Meta Description
  ...

## <Section Title>

- [Link Title](/link): Description
  ...

<Notes>

Configuration

Add custom sections:

nuxt.config.ts
export default defineNuxtConfig({
  aiReady: {
    llmsTxt: {
      sections: [
        {
          title: 'API Reference',
          links: [
            { title: 'REST API', href: '/docs/api', description: 'API documentation' }
          ]
        }
      ],
      notes: 'Built with Nuxt AI Ready'
    }
  }
})

Full config: Configuration

Hook

Modify sections before generation:

nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'ai-ready:llms-txt': (payload) => {
      payload.sections.push({
        title: 'Custom APIs',
        links: [{ title: 'Search', href: '/api/search', description: 'Search endpoint' }]
      })
      payload.notes.push('Custom note')
    }
  }
})

Hook details: Nuxt Hooks

/llms-full.txt

Full markdown content for all pages. Streamed during prerender — each page appended as processed, no memory accumulation.

Auto-generated from prerendered pages. Hook ai-ready:page:markdown fires per page if you need to modify content:

nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'ai-ready:page:markdown': (ctx) => {
      // ctx: { route, markdown, title, description }
      ctx.markdown = `# ${ctx.title}\n\n${ctx.markdown}`
    }
  }
})

How Pages Are Discovered

Page discovery uses a two-phase approach combining prerendering and sitemap crawling.

Phase 1: Prerender Crawl

During nuxi generate, the module intercepts each prerendered page:

  1. Nuxt plugin queues .md route for each rendered page
  2. Middleware converts HTML → markdown with metadata extraction
  3. ai-ready:page:markdown hook fires for each page
  4. Data appended to page-data.jsonl + streamed to llms-full.txt

Prerendered pages have full metadata (title, description, headings).

Phase 2: Sitemap Crawl

After prerendering completes, the module crawls /sitemap.xml for any pages not already processed:

  • Uses sitemap:prerender:done hook when @nuxtjs/sitemap is installed
  • Falls back to prerender:done hook otherwise
  • Fetches .md for each sitemap URL not in prerender set
  • Adds to page-data.jsonl but skips llms-full.txt (prevents duplicates)

This catches SSR-only pages that weren't prerendered.

Runtime Fallback

In SSR-only mode (no prerendering), llms.txt dynamically fetches /sitemap.xml and lists URLs without titles.

Phase 1 (Prerender)     Phase 2 (Sitemap)       Runtime
─────────────────────   ─────────────────────   ─────────────────────
app:rendered            sitemap:prerender:done  GET /llms.txt
    ↓                       ↓                       ↓
Queue .md routes        Parse sitemap.xml       fetchSitemapUrls()
    ↓                       ↓                       ↓
HTML → Markdown         Fetch .md for SSR       Combine prerendered
    ↓                   pages                   + sitemap URLs
Write JSONL +               ↓                       ↓
llms-full.txt           Add to JSONL only       Generate llms.txt

Customizing Page Processing

Filter or Modify Pages

Use the ai-ready:page:markdown hook to modify or filter pages during prerender:

nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'ai-ready:page:markdown': (ctx) => {
      // Skip draft pages
      if (ctx.route.startsWith('/drafts/')) {
        ctx.markdown = '' // Empty markdown = excluded from llms-full.txt
        return
      }

      // Add frontmatter
      ctx.markdown = `---
route: ${ctx.route}
title: ${ctx.title}
---

${ctx.markdown}`
    }
  }
})

Context properties:

  • route: Page path (e.g., /about)
  • markdown: Converted content (mutable)
  • title: Extracted <title>
  • description: Extracted meta description
  • headings: Array of { level, text } objects

Modify Markdown Conversion

Use the ai-ready:mdreamConfig Nitro hook to customize HTML → markdown:

server/plugins/mdream.ts
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('ai-ready:mdreamConfig', (config) => {
    // Skip navigation elements
    config.ignoreSelectors = ['nav', '.sidebar', '.footer']

    // Preserve code blocks
    config.preserveCodeBlocks = true
  })
})

Post-Process Markdown at Runtime

Use the ai-ready:markdown Nitro hook for runtime .md requests:

server/plugins/markdown.ts
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('ai-ready:markdown', (ctx) => {
    // Add source link
    ctx.markdown += `\n\n---\nSource: ${ctx.route}`
  })
})

Sitemap Requirements

The module requires @nuxtjs/sitemap for page discovery:

nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxtjs/sitemap', 'nuxt-ai-ready']
})

If sitemap is missing or empty, llms.txt will have an empty pages section with a warning logged.

Excluding Pages

Pages excluded from sitemap are automatically excluded from llms.txt. Use sitemap's exclude option:

nuxt.config.ts
export default defineNuxtConfig({
  sitemap: {
    exclude: ['/admin/**', '/api/**', '/drafts/**']
  }
})

Dev Mode

In development, llms.txt returns a notice about missing data. Page data is only available after nuxi generate or nuxi build --prerender.

Runtime .md routes still work in dev for testing markdown conversion.

Did this page help you?