---
title: "Nitro Hooks · Nuxt AI Ready · Nuxt SEO"
canonical_url: "https://nuxtseo.com/docs/ai-ready/nitro-api/nitro-hooks"
last_updated: "2026-08-16T09:50:33.565Z"
meta:
  description: "Nitro runtime hooks for modifying markdown output."
  "og:description": "Nitro runtime hooks for modifying markdown output."
  "og:title": "Nitro Hooks · Nuxt AI Ready · Nuxt SEO"
---

Nuxt SEO on GitHub

Switch to AI ReadySwitch to Nuxt SEOSwitch to RobotsSwitch to SitemapSwitch to OG ImageSwitch to Schema.orgSwitch to Link CheckerSwitch to SEO UtilsSwitch to Site ConfigSwitch to Skew Protection

**Nitro API**

# **Nitro Hooks**

## `**'ai-ready:page:markdown'**`

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

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

server/plugins/markdown-footer.ts

```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'**`

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

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

server/plugins/mdream-config.ts

```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:

server/plugins/custom-mdream.ts

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

## `**'ai-ready:page:indexed'**`

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

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

server/plugins/embeddings.ts

```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:

server/api/reindex.post.ts

```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**` |

**Was this page helpful?**

### **Related **

[**Markdown Conversion**](https://nuxtseo.com/docs/ai-ready/guides/markdown)

[**Nuxt Hooks**](https://nuxtseo.com/docs/ai-ready/api/nuxt-hooks)

[**Configuration**](https://nuxtseo.com/docs/ai-ready/api/config)

[**Composables** Server-side composables for accessing page data at runtime.](https://nuxtseo.com/docs/ai-ready/nitro-api/composables) [**v1.0.0** Release notes for Nuxt AI Ready v1.](https://nuxtseo.com/docs/ai-ready/releases/v1)