Index of every page on this site: llms.txt

Nitro Hooks

These hooks run in the Nitro server. Use Nuxt hooks for build-time output.

'ai-ready:page:markdown'

Type: (ctx: MarkdownContext) => void | Promise<void>

Runs when the module converts rendered HTML to Markdown: a runtime .md request, prerendering, and page indexing. Change ctx.markdown before the module serves, writes, or stores it. A supplied Markdown source bypasses this conversion hook.

server/plugins/markdown-footer.ts
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('ai-ready:page:markdown', (ctx) => {
    ctx.markdown += '\n\n---\n*Generated with mdream*'
  })
})

MarkdownContext:

PropertyTypeDescription
htmlstringOriginal HTML
markdownstringGenerated markdown (modify this)
routestringThe route the module is processing
titlestringPage title
descriptionstringPage description
isPrerenderbooleantrue during prerendering, false for a runtime request
eventH3Event | undefinedH3 event object. Undefined when indexing runs outside a request

'ai-ready:mdreamConfig'

Type: (config: MdreamOptions) => void | Promise<void>

Runs before the module converts rendered HTML to Markdown: at runtime, during prerendering, and during page indexing. Change mdream options for that conversion. Source Markdown does not call this hook.

server/plugins/mdream-config.ts
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('ai-ready:mdreamConfig', (config) => {
    config.filter ??= {}
    config.filter.exclude = [...(config.filter.exclude || []), '.author-bio']
  })
})

The hook receives conversion options, without a route field. config.origin contains only the origin. If you need to change a particular page's Markdown, use ctx.route in ai-ready:page:markdown.

'ai-ready:page:indexed'

Type: (ctx: PageIndexedContext) => void | Promise<void>

Runs after runtime indexing writes a page to the database. Check contentChanged before updating another system.

server/plugins/indexed-pages.ts
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('ai-ready:page:indexed', (ctx) => {
    if (!ctx.contentChanged)
      return

    console.info(`Changed page: ${ctx.route}`)
  })
})

Replace the log with your integration. First indexing counts as a change. isUpdate only tells you whether an indexed row already existed. A forced reindex of unchanged content can run the hook with contentChanged: false.

If an external call fails, retry that call separately. The stored hash already changed before the hook ran. A freshness skip or skipHook: true prevents this hook from running. The IndexNow recipe shows a changed-URL submission.

PageIndexedContext:

PropertyTypeDescription
routestringPage route
titlestringPage title
descriptionstringPage description
headingsArray<Record<string, string>>Parsed headings, such as [{ h1: "Title" }]
keywordsstring[]Extracted keywords from content
markdownstringFull markdown content
updatedAtstringISO timestamp
isUpdatebooleantrue if an indexed row existed
contentChangedbooleanWhether the converted Markdown hash differs

Manual Indexing Utils

Use indexPage when you have HTML, or indexPageByRoute when the module should fetch it. These functions belong in trusted server code. See Composables for complete examples.

OptionTypeDescription
ttlnumberOverride the freshness window in seconds
forcebooleanReindex even if fresh
skipHookbooleanSkip ai-ready:page:indexed

indexPageByRoute takes the event as its second argument. indexPage takes it as the fourth argument.

'ai-ready:markdown:source'

Supply Markdown you already hold instead of converting the rendered HTML. The route has no .md suffix. Leave ctx.source as null to use normal conversion.

server/plugins/markdown-source.ts
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('ai-ready:markdown:source', (ctx) => {
    if (ctx.route === '/about') {
      ctx.source = {
        title: 'About',
        markdown: '# About\n\nOur documentation site.',
      }
    }
  })
})

The payload contains route: string, event: H3Event, and source: MarkdownSource | null. A source requires markdown. It may also provide title, description, and updatedAt. The module adds its frontmatter to the supplied body. This hook serves Markdown; it does not update the runtime page index.

If the source has page metadata, include it directly in source.markdown. Image fields stay in frontmatter. JSON-LD stays in a JSON fence:

---
meta:
  og:image: https://example.com/cover.png
---

# About

```json
{"@context":"https://schema.org","@type":"Article","headline":"About"}
```

The module preserves these source fields while adding its title, canonical URL, and other supplied metadata. It does not fetch HTML to find missing fields or apply HTML conversion limits to supplied Markdown.

Was this page helpful?