Composables · Nuxt AI Ready · Nuxt SEO

-
-
-
-

[Sign In](https://nuxtseo.com/auth/github)

[Nuxt SEO on GitHub](https://github.com/harlan-zw/nuxt-seo)

AI Ready

-
-
-
-
-
-
-
-
-
-

Search…```k`` /`

v1.1.2

- [Discord Support](https://discord.com/invite/275MBUBvgP)

### Nuxt API

-
-

### Nitro API

-
-

Nitro API

# Composables

[Copy for LLMs](https://nuxtseo.com/docs/ai-ready/nitro-api/composables.md)

These composables are auto-imported in Nitro server context (API routes, middleware, plugins).

## [`queryPages`](#querypages)

**Type:** `(event?: H3Event, options?: QueryPagesOptions) => Promise<PageEntry[]| PageData[]>`

Unified page query function with filtering, pagination, and optional markdown content.

server/api/pages.get.ts

```
import { queryPages } from '#ai-ready'

export default defineEventHandler(async (event) => {
  // Get all pages
  const pages = await queryPages(event)
  return pages
})
```

**Single page lookup:**

server/api/page.get.ts

```
export default defineEventHandler(async (event) => {
  const { path } = getQuery(event)
  const page = await queryPages(event, { route: path as string, includeMarkdown: true })
  return page
})
```

**QueryPagesOptions:**

| Option | Type | Description |
| --- | --- | --- |
| `route` | `string` | Get single page by route |
| `includeMarkdown` | `boolean` | Include markdown content |
| `where.pending` | `boolean` | Filter by indexing status |
| `where.hasError` | `boolean` | Filter by error status |
| `where.source` | `'prerender' \| 'runtime'` | Filter by source |
| `limit` | `number` | Max pages to return |
| `offset` | `number` | Skip first N pages |

**PageEntry:**

| Property | Type | Description |
| --- | --- | --- |
| `route` | `string` | Page route (e.g., `/about`) |
| `title` | `string` | Page title |
| `description` | `string` | Meta description |
| `headings` | `string` | Pipe-separated headings (e.g., `h1:Title\|h2:Subtitle`) |
| `keywords` | `string[]` | Extracted keywords |
| `updatedAt` | `string` | ISO timestamp |

**PageData:** Extends PageEntry with `markdown: string`.

## [`searchPages`](#searchpages)

**Type:** `(event: H3Event, query: string, options?: SearchPagesOptions) => Promise<SearchResult[]>`

Full-text search using SQLite FTS5. Searches title, description, route, headings, keywords, and markdown content.

server/api/search.get.ts

```
import { searchPages } from '#ai-ready'

export default defineEventHandler(async (event) => {
  const { q } = getQuery(event)
  return searchPages(event, q as string, { limit: 10 })
})
```

**SearchResult:**

| Property | Type | Description |
| --- | --- | --- |
| `route` | `string` | Page route |
| `title` | `string` | Page title |
| `description` | `string` | Meta description |
| `score` | `number` | BM25 relevance score |

## [`countPages`](#countpages)

**Type:** `(event?: H3Event, options?: CountPagesOptions) => Promise<number>`

Count pages matching criteria.

server/api/stats.get.ts

```
import { countPages } from '#ai-ready'

export default defineEventHandler(async (event) => {
  const total = await countPages(event)
  const pending = await countPages(event, { where: { pending: true } })
  return { total, pending, indexed: total - pending }
})
```

## [`streamPages`](#streampages)

**Type:** `(event?: H3Event, options?: StreamPagesOptions) => AsyncGenerator<PageData>`

Stream pages using cursor-based pagination. Useful for large datasets.

server/api/export.get.ts

```
import { streamPages } from '#ai-ready'

export default defineEventHandler(async (event) => {
  const pages = []
  for await (const page of streamPages(event, { batchSize: 50 })) {
    pages.push({ route: page.route, title: page.title })
  }
  return pages
})
```

## [`indexPage`](#indexpage)

**Type:** `(route: string, html: string, options?: IndexPageOptions) => Promise<IndexPageResult>`

Manually index a page into the database.

server/api/reindex.post.ts

```
import { indexPage } from '#ai-ready'

export default defineEventHandler(async (event) => {
  const { path } = await readBody(event)
  const html = await $fetch(path)
  return indexPage(path, html, { force: true })
})
```

**Options:**

| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `ttl` | `number` | config value | Override TTL check |
| `force` | `boolean` | `false` | Re-index even if fresh |
| `skipHook` | `boolean` | `false` | Skip `ai-ready:page:indexed` hook |

**Result:**

| Property | Type | Description |
| --- | --- | --- |
| `success` | `boolean` | Whether indexing succeeded |
| `skipped` | `boolean` | `true` if page was fresh |
| `isUpdate` | `boolean` | `true` if updating existing entry |
| `contentChanged` | `boolean` | `true` if content hash differs |
| `data` | `object` | Page data if successful |
| `error` | `string` | Error message if failed |

## [`indexPageByRoute`](#indexpagebyroute)

**Type:** `(route: string, event?: H3Event, options?: IndexPageOptions) => Promise<IndexPageResult>`

Fetch HTML and index in one call.

server/plugins/warm-cache.ts

```
import { indexPageByRoute } from '#ai-ready'

export default defineNitroPlugin(async () => {
  // Pre-warm important pages on startup
  const routes = ['/', '/docs', '/pricing']
  await Promise.all(routes.map(r => indexPageByRoute(r)))
})
```

## [`useDatabase`](#usedatabase)

**Type:** `(event?: H3Event) => Promise<DatabaseAdapter>`

Direct database access for advanced queries.

server/api/custom.get.ts

```
import { useDatabase } from '#ai-ready'

export default defineEventHandler(async (event) => {
  const db = await useDatabase(event)
  const rows = await db.all('SELECT route, title FROM ai_ready_pages WHERE indexed = 1')
  return rows
})
```

## [Data Sources](#data-sources)

| Context | Source |
| --- | --- |
| Development | Empty (warning logged) |
| Prerender | [SQLite](https://sqlite.org) via virtual module |
| Runtime | SQLite via db0 |

[Edit this page](https://github.com/nuxt-seo-pro/nuxt-ai-ready/edit/main/docs/content/3.nitro-api/1.composables.md)

[Markdown For LLMs](https://nuxtseo.com/docs/ai-ready/nitro-api/composables.md)

Did this page help you?

### Related

On this page

- [queryPages](#querypages)
- [searchPages](#searchpages)
- [countPages](#countpages)
- [streamPages](#streampages)
- [indexPage](#indexpage)
- [indexPageByRoute](#indexpagebyroute)
- [useDatabase](#usedatabase)
- [Data Sources](#data-sources)

[GitHub](https://github.com/harlan-zw/nuxt-seo) [ Discord](https://discord.com/invite/275MBUBvgP)

###

-
-

Modules

-
-
-
-
-
-
-
-
-

###

-
-
-

###

Nuxt

-
-
-
-
-

Vue

-
-
-
-
-
-
-
-

###

-
-
-
-
-
-
-
-
-
-

Copyright © 2023-2026 Harlan Wilton - [MIT License](https://github.com/harlan-zw/nuxt-seo/blob/main/license) · [mdream](https://mdream.dev)