---
title: "Nitro Hooks"
description: "Nitro runtime hooks for modifying markdown output."
canonical_url: "https://nuxtseo.com/docs/ai-ready/nitro-api/nitro-hooks"
last_updated: "2026-09-05T17:04:07.133Z"
---

## `'ai-ready:page:markdown'`{lang="ts"}

**Type:** `(ctx: MarkdownContext) => void | Promise<void>`{lang="ts"}

Called during runtime HTML→markdown conversion. Modify markdown before response.

```ts [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:**

| Property      | Type      | Description                        |
| ------------- | --------- | ---------------------------------- |
| `html`        | `string`  | Original HTML                      |
| `markdown`    | `string`  | Generated markdown (modify this)   |
| `route`       | `string`  | The route the module is processing |
| `title`       | `string`  | Page title                         |
| `description` | `string`  | Page description                   |
| `isPrerender` | `boolean` | Whether during prerendering        |
| `event`       | `H3Event` | H3 event object                    |

## `'ai-ready:mdreamConfig'`{lang="ts"}

**Type:** `(config: MdreamOptions) => void | Promise<void>`{lang="ts"}

Called before HTML→markdown conversion. Modify mdream options per-request.

```ts [server/plugins/mdream-config.ts]
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('ai-ready:mdreamConfig', (config) => {
    // Check origin from config.origin if available
    if (config.origin?.includes('/blog/'))
      config.ignoreElements = [...(config.ignoreElements || []), '.author-bio']
  })
})
```

Add custom plugins:

```ts [server/plugins/custom-mdream.ts]
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('ai-ready:mdreamConfig', (config) => {
    config.plugins = config.plugins || []
    config.plugins.push(myCustomPlugin())
  })
})
```

## `'ai-ready:page:indexed'`{lang="ts"}

**Type:** `(ctx: PageIndexedContext) => void | Promise<void>`{lang="ts"}

Called when a page is indexed at runtime. Use this to sync with external systems like vector databases or search indexes.

```ts [server/plugins/embeddings.ts]
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('ai-ready:page:indexed', async (ctx) => {
    // Generate embeddings for new pages
    if (!ctx.isUpdate) {
      await generateEmbeddings(ctx.route, ctx.markdown)
    }
    // Or always update
    await updateSearchIndex(ctx)
  })
})
```

**PageIndexedContext:**

| Property      | Type       | Description                                             |
| ------------- | ---------- | ------------------------------------------------------- |
| `route`       | `string`   | Page route                                              |
| `title`       | `string`   | Page title                                              |
| `description` | `string`   | Page description                                        |
| `headings`    | `string`   | Pipe-delimited headings (e.g., `h1:Title\|h2:Subtitle`) |
| `keywords`    | `string[]` | Extracted keywords from content                         |
| `markdown`    | `string`   | Full markdown content                                   |
| `updatedAt`   | `string`   | ISO timestamp                                           |
| `isUpdate`    | `boolean`  | `true` if re-indexing existing page                     |

## Manual Indexing Utils

For custom indexing logic, use the exported utilities:

```ts [server/api/reindex.post.ts]
import { indexPage, indexPageByRoute } from '#ai-ready'

export default defineEventHandler(async (event) => {
  const { path } = await readBody(event)

  // Option 1: Index with HTML you already have
  const html = await fetchHtmlSomehow(path)
  const result = await indexPage(path, html, { force: true })

  // Option 2: Fetch and index in one call
  const result = await indexPageByRoute(path, event, { force: true })

  return result
})
```

**Options:**

| Option     | Type      | Description                        |
| ---------- | --------- | ---------------------------------- |
| `ttl`      | `number`  | Override config TTL                |
| `force`    | `boolean` | Re-index even if fresh             |
| `skipHook` | `boolean` | Don't call `ai-ready:page:indexed` |