---
title: "Configuration"
description: "Nuxt configuration reference for Nuxt AI Ready."
canonical_url: "https://nuxtseo.com/docs/ai-ready/api/config"
last_updated: "2026-09-25T20:11:21.282Z"
---

Set module options under `aiReady` in your Nuxt configuration. Defaults below describe the current module.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  aiReady: {
    // options
  }
})
```

## `enabled: boolean`{lang="ts"}

- Default: `true`{lang="ts"}

```ts
aiReady: {
  enabled: process.env.NODE_ENV === 'production'
}
```

## `debug: boolean`{lang="ts"}

- Default: `false`{lang="ts"}

Enable debug logging for module operations.

## `contentNegotiation: boolean`{lang="ts"}

- Default: Automatic per route

Set `false`{lang="ts"} to keep original page URLs as HTML, even when requests prefer Markdown through `Accept`{lang="http"} or an AI crawler `User-Agent`{lang="http"}. Explicit `.md` URLs, alternate links, `llms.txt`, MCP, and page indexing remain available.

In automatic mode, the module reads the effective route rule for each request. It disables negotiation for ISR and for Nitro response caches whose `varies`{lang="ts"} list is missing `accept`{lang="http"}, `sec-fetch-dest`{lang="http"}, or `user-agent`{lang="http"}. This includes `swr`{lang="ts"} rules after Nitro normalizes them. `headersOnly: true`{lang="ts"} remains safe because it does not cache the response body.

Set `false`{lang="ts"} for URL-only CDN or reverse proxy caching configured outside Nuxt. Set `true`{lang="ts"} to force negotiation and take responsibility for the cache key.

```ts
export default defineNuxtConfig({
  aiReady: {
    contentNegotiation: false
  }
})
```

## `apiCatalog: false | ApiCatalogConfig`{lang="ts"}

- Default: Disabled until you configure entries or an integration generates them

Publish an [RFC 9727 API Catalog](/docs/ai-ready/guides/api-catalog) at `/.well-known/api-catalog`{lang="bash"}. Relative URLs resolve against `site.url`{lang="ts"} and `app.baseURL`{lang="ts"} once during module setup. Non-root apps redirect the origin-root request to the base-aware route.

```ts
export default defineNuxtConfig({
  site: {
    url: 'https://example.com',
  },
  aiReady: {
    apiCatalog: {
      entries: [{
        anchor: '/api',
        serviceDesc: {
          href: '/openapi.json',
          type: 'application/vnd.oai.openapi+json;version=3.1',
        },
        serviceDoc: { href: '/docs/api', type: 'text/html' },
        status: { href: '/api/health', type: 'application/json' },
      }],
    },
  },
})
```

Each entry needs at least one relation target. A relation accepts one target or an array. Supported typed relations are `item`{lang="ts"}, `serviceDesc`{lang="ts"}, `serviceDoc`{lang="ts"}, `serviceMeta`{lang="ts"}, `status`{lang="ts"}, and `apiCatalog`{lang="ts"}. Use `relations`{lang="ts"} for other RFC 8288 relation names. Set `apiCatalog: false`{lang="ts"} to suppress configured and integration-generated entries.

## `mdreamOptions: MdreamOptions`{lang="ts"}

- Default: `{ minimal: true, clean: true }`{lang="ts"}

Configure [mdream](https://github.com/harlan-zw/mdream) HTML-to-markdown conversion.

```ts
export default defineNuxtConfig({
  aiReady: {
    mdreamOptions: {
      minimal: true
    }
  }
})
```

## `markdownCacheHeaders: { maxAge?: number, swr?: boolean }`{lang="ts"}

- Default: `{ maxAge: 3600, swr: true }`{lang="ts"}

Cache settings for runtime markdown endpoints.

| Option   | Type      | Default | Description               |
| -------- | --------- | ------- | ------------------------- |
| `maxAge` | `number`  | `3600`  | Cache duration in seconds |
| `swr`    | `boolean` | `true`  | Stale-while-revalidate    |

## `agentSkills: false | AgentSkillsConfig`{lang="ts"}

- Default: `{}`{lang="ts"}

Publish an [Agent Skills Discovery v0.2.0 index](/docs/ai-ready/guides/agent-skills).
The module finds `skills/<name>/SKILL.md`{lang="text"} files in your project and its layers.
It serves each file at `/.well-known/agent-skills/<name>/SKILL.md`{lang="text"} and `/skills/<name>/SKILL.md`{lang="text"}.
For one skill, or the skill selected by `root`, it also serves `/SKILL.md`{lang="text"}.

The module lists discovered skills in llms.txt. With no skills, it publishes nothing.
Use `dir` to change the folder or disable discovery. Use `skills` to add local or external entries.
Set `llmsTxt: false` to leave llms.txt alone, or `agentSkills: false` to disable publication.
The `ai-ready:agent-skills` hook sees every entry before publication.

```ts
aiReady: {
  agentSkills: {
    skills: [{
      source: 'local',
      name: 'seo-audit',
      description: 'Audit a site for critical SEO issues.',
      file: './skills/seo-audit/SKILL.md'
    }]
  }
}
```

## `llmsTxt: LlmsTxtConfig`{lang="ts"}

- Default: Auto-generated

Configure llms.txt generation.

```ts
export default defineNuxtConfig({
  aiReady: {
    llmsTxt: {
      markdownLinks: true,
      sections: [
        {
          title: 'API Reference',
          links: [
            { title: 'REST API', href: '/docs/api', description: 'API docs' }
          ]
        },
        {
          title: 'Debug Endpoints',
          optional: true,
          links: [
            { title: 'Debug Route', href: '/__ai-ready-debug', description: 'Internal debugging' }
          ]
        }
      ],
      notes: 'Built with Nuxt AI Ready'
    }
  }
})
```

**LlmsTxtSection:**

| Property      | Type                              | Description                                                                                                     |
| ------------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `title`       | `string`                          | Section title                                                                                                   |
| `description` | `string \| string[]`              | Section context rendered in the heading-free preamble, or in each optional link note                            |
| `links`       | `{ title, href, description? }[]` | Links in section                                                                                                |
| `optional`    | `boolean`                         | Put the section's links in the single `## Optional` file list, which LLMs may skip with shorter context windows |

**LlmsTxtConfig:**

| Property        | Type                 | Description                                                                                                     |
| --------------- | -------------------- | --------------------------------------------------------------------------------------------------------------- |
| `markdownLinks` | `boolean`            | Link automatically generated page and locale entries to available Markdown representations. Defaults to `false` |
| `sections`      | `LlmsTxtSection[]`   | Custom sections                                                                                                 |
| `notes`         | `string \| string[]` | Additional heading-free context rendered before file-list sections                                              |

## `sitemapMd: boolean`{lang="ts"}

- Default: `true`{lang="ts"}

Generate a Markdown sitemap at `/sitemap.md`{lang="bash"} from indexed pages. The sitemap groups pages by top-level path segment under `##`{lang="ts"} headings. Each link points at the page’s `.md` representation. When a page records a last update, it becomes the link's title text.

The same flag appends a `## Sitemap`{lang="ts"} section to module-generated Markdown, linking back to `/sitemap.md`{lang="bash"}.

```ts
export default defineNuxtConfig({
  aiReady: {
    sitemapMd: false
  }
})
```

## `describedby: boolean`{lang="ts"}

- Default: `true`{lang="ts"}

Advertise llms.txt with `rel="describedby"`{lang="ts"} on HTML and Markdown responses. HTML pages get a `<link rel="describedby" href="/llms.txt">`{lang="html"} tag, and both variants get a `Link`{lang="http"} header entry.

```ts
export default defineNuxtConfig({
  aiReady: {
    describedby: false
  }
})
```

## `contentSignal: false | { aiTrain?: boolean, contentUsage?: boolean, search?: boolean, aiInput?: boolean }`{lang="ts"}

- Default: `false`{lang="ts"}

Content Signal directives for robots.txt. See [Content Signals guide](/docs/ai-ready/guides/content-signals).

```ts
export default defineNuxtConfig({
  aiReady: {
    contentSignal: {
      aiTrain: false, // Block training
      contentUsage: false, // Omit Content-Usage from robots.txt
      search: true, // Allow search indexing
      aiInput: true, // Allow RAG/grounding
    }
  }
})
```

## `tools: SiteToolsConfig`{lang="ts"}

Configure the three built-in tools once, then attach each one to MCP, WebMCP or both.

| Tool              | Shared options | `mcp` options | `webmcp` options                         |
| ----------------- | -------------- | ------------- | ---------------------------------------- |
| `listPages`       | `defaultLimit` | `enabled`     | `enabled`, `maxOutputChars`, `exposedTo` |
| `searchPages`     | `defaultLimit` | `enabled`     | `enabled`, `maxOutputChars`, `exposedTo` |
| `getPageMarkdown` | None           | `enabled`     | `enabled`, `maxOutputChars`, `exposedTo` |

`defaultLimit` defaults to 20 for `listPages` and 10 for `searchPages`. Values are clamped to 50. WebMCP output defaults to 1,500 characters per tool.

```ts
export default defineNuxtConfig({
  aiReady: {
    tools: {
      listPages: {
        defaultLimit: 10,
        webmcp: { enabled: false },
      },
      searchPages: {
        defaultLimit: 5,
        webmcp: { maxOutputChars: 3000 },
      },
    },
  },
})
```

The module enables omitted attachment objects when their transport is active. Set `mcp.enabled`{lang="ts"} or `webmcp.enabled`{lang="ts"} to `false` on one tool to leave it off that transport.

## `mcp: { tools?: boolean, resources?: boolean }`{lang="ts"}

- Default: `{ tools: true, resources: true }`{lang="ts"}

Control MCP features when `@nuxtjs/mcp-toolkit` installed.

```ts
export default defineNuxtConfig({
  aiReady: {
    mcp: {
      tools: true, // list_pages, search_pages, get_page_markdown
      resources: true, // pages resource
    }
  }
})
```

See [MCP guide](/docs/ai-ready/guides/mcp) for tool/resource details.

## `mcpServerCard: false | McpServerCardConfig`{lang="ts"}

- Default: `{ cacheMaxAge: 3600 }`{lang="ts"}

Publish experimental SEP-2127 discovery metadata at `<mcp-route>/server-card`{lang="bash"} when MCP Toolkit runs on the server. For the default Toolkit route, the card is available at `/mcp/server-card`{lang="bash"}. Set this option to `false` to disable the route.

| Option        | Type     | Default                              | Description                                         |
| ------------- | -------- | ------------------------------------ | --------------------------------------------------- |
| `name`        | `string` | Derived from site host and MCP route | Reverse-DNS/server identity                         |
| `title`       | `string` | Existing Toolkit or site name        | Human-readable server title                         |
| `description` | `string` | Toolkit or site description          | Server description, up to 100 characters            |
| `websiteUrl`  | `string` | None                                 | Absolute HTTP or HTTPS project or documentation URL |
| `cacheMaxAge` | `number` | `3600`                               | Browser and shared cache lifetime in seconds        |

Toolkit icons are copied into the card. The card route is omitted when Toolkit is absent, disabled or unavailable in a static deployment.

## `webmcp: boolean | WebMcpConfig`{lang="ts"}

- Default: `false`{lang="ts"}

Register [WebMCP](/docs/ai-ready/guides/webmcp) tools for browser agents through `document.modelContext`{lang="ts"}.

| Option      | Type       | Default | Description                                                                            |
| ----------- | ---------- | ------- | -------------------------------------------------------------------------------------- |
| `tools`     | `boolean`  | `true`  | Attach tools enabled under `aiReady.tools`                                             |
| `exposedTo` | `string[]` | None    | Default trusted origins for built-in and composable tools. Same-origin only by default |

```ts
export default defineNuxtConfig({
  aiReady: {
    tools: {
      listPages: {
        webmcp: { enabled: false },
      },
      searchPages: {
        defaultLimit: 20,
        webmcp: { maxOutputChars: 3000 },
      },
    },
    webmcp: {
      exposedTo: ['https://agent.example.com'],
    },
  },
})
```

Nuxt auto-imports `useWebMcpTool()`{lang="ts"} and `useWebMcpSupported()`{lang="ts"} when you enable WebMCP. Set `webmcp.tools`{lang="ts"} to `false` to register your own tools without the built-in definitions or `/__ai-ready/pages`{lang="bash"} endpoint.

## `llmsTxtCacheSeconds: number`{lang="ts"}

- Default: `600`{lang="ts"} (10 minutes)

Cache duration for llms.txt route handlers. Uses stale-while-revalidate.

```ts
export default defineNuxtConfig({
  aiReady: {
    llmsTxtCacheSeconds: 3600 // 1 hour
  }
})
```

## `database: false | { type?: string, filename?: string, bindingName?: string, url?: string, authToken?: string }`{lang="ts"}

- Default: Disabled until a requested feature needs stored pages.

Configure the database for page storage. The module auto-detects the best driver based on the deployment platform.

| Option        | Type                                                                      | Default                     | Description                                   |
| ------------- | ------------------------------------------------------------------------- | --------------------------- | --------------------------------------------- |
| `type`        | `'none' \| 'sqlite' \| 'bun' \| 'd1' \| 'libsql' \| 'neon' \| 'postgres'` | `'sqlite'`                  | Database type. `'none'` disables the database |
| `filename`    | `string`                                                                  | `'.data/ai-ready/pages.db'` | [SQLite](https://sqlite.org) file path        |
| `bindingName` | `string`                                                                  | `'DB'`                      | D1 binding name                               |
| `url`         | `string`                                                                  | -                           | LibSQL, Neon, or PostgreSQL URL               |
| `authToken`   | `string`                                                                  | -                           | LibSQL/Turso auth token                       |

::code-group
```ts [Default (SQLite)]
export default defineNuxtConfig({
  aiReady: {
    database: {
      filename: '.data/ai-ready/pages.db'
    }
  }
})
```

```ts [Cloudflare D1]
export default defineNuxtConfig({
  aiReady: {
    database: {
      type: 'd1',
      bindingName: 'DB'
    }
  }
})
```

```ts [Turso/LibSQL]
export default defineNuxtConfig({
  aiReady: {
    database: {
      type: 'libsql',
      url: process.env.TURSO_URL,
      authToken: process.env.TURSO_AUTH_TOKEN
    }
  }
})
```

```ts [PostgreSQL]
export default defineNuxtConfig({
  aiReady: {
    database: {
      type: 'postgres',
      url: process.env.DATABASE_URL
    }
  }
})
```

```ts [No database]
export default defineNuxtConfig({
  aiReady: {
    database: false
  }
})
```
::

**Driver auto-detection:**

| Platform                                           | Driver           | Extra dependency |
| -------------------------------------------------- | ---------------- | ---------------- |
| [Node.js](https://nodejs.org) 22.13+               | `node:sqlite`    | None             |
| Earlier [Node.js](https://nodejs.org)              | `better-sqlite3` | `better-sqlite3` |
| [Bun](https://bun.sh)                              | `bun:sqlite`     | None             |
| [Cloudflare](https://cloudflare.com)               | D1               | None             |
| [Vercel](https://vercel.com) (with `POSTGRES_URL`) | Neon Postgres    | None             |
| Node.js with `database.type: 'postgres'`           | PostgreSQL       | `postgres`       |

On Node.js before 22.13, the default `sqlite` type requires the optional [`better-sqlite3`](https://github.com/WiseLibs/better-sqlite3) peer dependency: `pnpm add better-sqlite3`{lang="bash"}.

For [PostgreSQL](https://postgresql.org), install the optional [`postgres`](https://github.com/porsager/postgres) peer dependency: `pnpm add postgres`{lang="bash"}. The driver reads `database.url`{lang="ts"}, `POSTGRES_URL`, then `DATABASE_URL`.

Prerendering creates a compressed dump. Runtime storage restores it when empty and checks build changes on later requests.

### No Database

The database stays off when no requested feature needs stored pages.
Set `database: false`{lang="ts"} (or `database: { type: 'none' }`{lang="ts"}) to force it off.
No driver enters the server bundle, so the runtime needs no `better-sqlite3`.
On Node.js before 22.13, build time indexing needs `better-sqlite3`.

Runtime indexing, MCP page tools or resources, and WebMCP page tools enable storage automatically.
An explicit database config also enables storage.

Build-time generation still works. You keep:

- `llms.txt` and `llms-full.txt`, written during prerender.
- `.md` twins for every prerendered page.
- The `Link` headers, configured content signals, API Catalog and Agent Skills.

Runtime Markdown conversion remains available without a database when the deployment retains a server.
A fully static deployment can only serve its generated files.

The following features need stored pages:

- `list_pages`, `search_pages` and `get_page_markdown`, for both MCP and WebMCP.
- The MCP pages resource.
- Runtime `llms-full.txt` needs stored pages to include page bodies. Prerender the route for static output.

A disabled database conflicts with `runtimeSync` and `cron`.
If you set any of them, the build fails with a message naming the option.

**Table naming:**

The module uses these reserved table names:

- `ai_ready_pages` : Main pages table
- `ai_ready_pages_fts` : FTS5 full-text search index
- `_ai_ready_info` : Schema version tracking

The prefixes separate these tables from unrelated application tables. Do not reuse the same table names for other data.

## `cron: boolean`{lang="ts"}

- Default: `false`{lang="ts"}

Enable the scheduled task that runs every 5 minutes. It automatically enables `runtimeSync` for background indexing.

```ts
export default defineNuxtConfig({
  aiReady: {
    cron: true
  }
})
```

## `runtimeSyncSecret: string`{lang="ts"}

- Default: Generated when you enable `runtimeSync` or `cron`

Secret token for runtime control endpoints. Send it in the `Authorization: Bearer <token>`{lang="http"} header.

Setup uses explicit config, then `NUXT_AI_READY_RUNTIME_SYNC_SECRET`, then a generated value when you enable runtime sync.
Use a stable configured secret for external schedulers and the CLI. Setup writes the chosen secret into the local CLI cache.
Status requests also authenticate; prune dry runs are the exception.

```ts
export default defineNuxtConfig({
  aiReady: {
    runtimeSyncSecret: process.env.AI_READY_SECRET
  }
})
```

## `runtimeSync: boolean | { ttl?: number, batchSize?: number, pruneTtl?: number }`{lang="ts"}

- Default: `false`{lang="ts"}

Enable runtime controls and sitemap seeding for content that changes between deployments.
Set `true` for defaults, or use an object to change them.

Poll and cron process pending pages. TTL expiry alone does not mark an already indexed page pending.
When a published page changes between builds, call the authenticated reindex endpoint or a manual indexing utility.

| Option      | Type     | Default | Description                                                                 |
| ----------- | -------- | ------- | --------------------------------------------------------------------------- |
| `ttl`       | `number` | `3600`  | Freshness window for manual indexing and sitemap refresh interval (seconds) |
| `batchSize` | `number` | `50`    | Pages per batch (max: 50)                                                   |
| `pruneTtl`  | `number` | `0`     | Prune routes not seen in the sitemap for this many seconds (0 = disabled)   |

```ts
export default defineNuxtConfig({
  aiReady: {
    runtimeSync: {
      ttl: 3600,
      batchSize: 20,
      pruneTtl: 604800 // prune after 7 days
    },
    runtimeSyncSecret: process.env.AI_READY_SECRET,
    cron: true // enable scheduled indexing
  }
})
```

**When enabled:**

- `GET /__ai-ready/status` : Check indexing progress
- `POST /__ai-ready/poll` : Trigger batch indexing (requires `Authorization: Bearer <token>`{lang="html"} header)
- `POST /__ai-ready/prune` : Prune stale routes (requires `Authorization: Bearer <token>`{lang="html"} header)
- `POST /__ai-ready/reindex?route=/about`{lang="bash"} - Reindex a single route (requires `Authorization: Bearer <token>`{lang="html"} header)

See [Runtime Sync guide](/docs/ai-ready/guides/runtime-indexing) for details.

## `autoI18n: boolean`{lang="ts"}

- Default: `true`{lang="ts"}

Auto-detect [`@nuxtjs/i18n`](https://i18n.nuxtjs.org/) (or `nuxt-i18n-micro`) at build time and integrate locale data into:

- **`llms.txt`**: adds an `## Available Languages on Website` file-list section linking to every locale root
- **`Link` headers**: emits `Link: <…>; rel="alternate"; hreflang="…"` per locale on `.md` and HTML responses (RFC 8288)
- **Frontmatter**: runtime HTML-to-Markdown responses include a `locale` field
- **Database**: each indexed page persists its `locale` for filtered queries
- **FTS5 tokenizer**: auto-switches to `trigram` for CJK locales (zh / ja / ko)

Disable to skip the integration even with an i18n module present:

```ts
export default defineNuxtConfig({
  aiReady: {
    autoI18n: false
  }
})
```

See [i18n guide](/docs/ai-ready/guides/i18n) for details.

## `contentSource: boolean`{lang="ts"}

- Default: `true`{lang="ts"}

Read Markdown directly from page collections in `@nuxt/content` v3 or `@harlan-zw/comark-content` when available.
Set `false` to convert rendered HTML instead. Use that when a page’s meaning depends on its rendered components.
See [Markdown Conversion](/docs/ai-ready/guides/markdown) for source lookup behavior.

## `prerender: { concurrency?: number }`{lang="ts"}

- Default concurrency: `10`{lang="ts"}

Control how many pages the module processes concurrently during prerendering. Set `1` to process one page at a time.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  aiReady: {
    prerender: { concurrency: 5 },
  },
})
```

## `debugCron: boolean`{lang="ts"}

- Default: `false`{lang="ts"}

Record cron runs in the database for diagnostics. Enable it when investigating scheduled indexing.
This option does not enable cron itself.

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
