'ai-ready:markdown'

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

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

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

MarkdownContext:

PropertyTypeDescription
htmlstringOriginal HTML
markdownstringGenerated markdown (modify this)
routestringRoute being processed
titlestringPage title
descriptionstringPage description
isPrerenderbooleanWhether during prerendering
eventH3EventH3 event object

'ai-ready:mdreamConfig'

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

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

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:

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'

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

PropertyTypeDescription
routestringPage route
titlestringPage title
descriptionstringPage description
headingsstringPipe-delimited headings (e.g., h1:Title|h2:Subtitle)
keywordsstring[]Extracted keywords from content
markdownstringFull markdown content
updatedAtstringISO timestamp
isUpdatebooleantrue if re-indexing existing page

Manual Indexing Utils

For custom indexing logic, use the exported utilities:

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:

OptionTypeDescription
ttlnumberOverride config TTL
forcebooleanRe-index even if fresh
skipHookbooleanDon't call ai-ready:page:indexed
Did this page help you?