---
title: "Nuxt Content"
description: "How to use the Nuxt Sitemap module with Nuxt Content."
canonical_url: "https://nuxtseo.com/docs/sitemap/guides/content"
last_updated: "2026-05-07T08:43:53.684Z"
---

## Introduction

Nuxt Sitemap comes with an integration for Nuxt Content that allows you to configure your sitemap entry straight from your content files directly.

### Supported Content Types

The sitemap integration works with all content file types supported by Nuxt Content:

- Markdown (`.md`)
- YAML (`.yml` / `.yaml`)
- JSON (`.json`)
- CSV (`.csv`)

## Setup Nuxt Content v3

Add `defineSitemapSchema()` to your collection's schema to enable the `sitemap` frontmatter key.

```ts [content.config.ts]
import { defineCollection, defineContentConfig } from '@nuxt/content'
import { defineSitemapSchema } from '@nuxtjs/sitemap/content'
import { z } from 'zod'

export default defineContentConfig({
  collections: {
    content: defineCollection({
      type: 'page',
      source: '**/*.md',
      schema: z.object({
        sitemap: defineSitemapSchema(),
      }),
    }),
  },
})
```

### Filtering Content

Pass a `filter` function to `defineSitemapSchema()` to exclude entries at runtime. This is useful for filtering out draft posts, future content, or any entries that shouldn't appear in the sitemap.

```ts [content.config.ts]
import { defineCollection, defineContentConfig } from '@nuxt/content'
import { defineSitemapSchema } from '@nuxtjs/sitemap/content'
import { z } from 'zod'

export default defineContentConfig({
  collections: {
    // The `name` option must match the collection key
    blog: defineCollection({
      type: 'page',
      source: 'blog/**/*.md',
      schema: z.object({
        date: z.string().optional(),
        draft: z.boolean().optional(),
        sitemap: defineSitemapSchema({
          name: 'blog',
          filter: (entry) => {
            if (entry.draft)
              return false
            if (entry.date && new Date(entry.date) > new Date())
              return false
            return true
          },
        }),
      }),
    }),
  },
})
```

<important>

The `name` option must match the collection key exactly (e.g. if your collection key is `blog`, use `name: 'blog'`). This is how the filter is matched to the correct collection at runtime.

</important>

The `filter` function receives the full content entry including your custom schema fields and should return `true` to include, `false` to exclude.

### Transforming URLs with `onUrl`

Use the `onUrl` callback to transform the sitemap entry for each item in a collection. The callback receives the resolved URL object; mutate it directly to change `loc`, `lastmod`, `priority`, or any other field.

This is especially useful when using per-locale collections with `@nuxtjs/i18n`. If a collection uses `prefix: '/'` or `prefix: ''` to strip the locale directory from content paths, the sitemap URLs will be missing the locale prefix. Use `onUrl` to re-add it:

```ts [content.config.ts]
import { defineCollection, defineContentConfig } from '@nuxt/content'
import { defineSitemapSchema } from '@nuxtjs/sitemap/content'
import { z } from 'zod'

export default defineContentConfig({
  collections: {
    content_en: defineCollection({
      type: 'page',
      source: { include: 'en/**', prefix: '/' },
      schema: z.object({
        sitemap: defineSitemapSchema(),
      }),
    }),
    content_ja: defineCollection({
      type: 'page',
      source: { include: 'ja/**', prefix: '/' },
      schema: z.object({
        sitemap: defineSitemapSchema({
          name: 'content_ja',
          onUrl(url) {
            url.loc = `/ja${url.loc}`
          },
        }),
      }),
    }),
  },
})
```

Without `onUrl`, both collections would produce `loc: '/about'` for their `about.md` files. With the transform, the ja collection entries correctly produce `loc: '/ja/about'`, allowing the i18n sitemap builder to assign them to the correct per-locale sitemap.

The callback also receives the full content entry and collection name, so you can use any content field to drive sitemap values:

```ts
schema: z.object({
  featured: z.boolean().optional(),
  sitemap: defineSitemapSchema({
    name: 'blog',
    onUrl(url, entry, collection) {
      url.loc = url.loc.replace('/posts/', '/blog/')
      url.priority = entry.featured ? 1.0 : 0.5
    },
  }),
})
```

<important>

The `name` option must match the collection key exactly (e.g. if your collection key is `content_ja`, use `name: 'content_ja'`).

</important>

Due to current Nuxt Content v3 limitations, you must load the sitemap module before the content module.

```ts
export default defineNuxtConfig({
  modules: [
    '@nuxtjs/sitemap',
    '@nuxt/content' // <-- Must be after @nuxtjs/sitemap
  ]
})
```

## Setup Nuxt Content v2

In Nuxt Content v2 markdown files require either [Document Driven Mode](https://content.nuxt.com/document-driven/introduction), a `path` key to be set
in the frontmatter or the `strictNuxtContentPaths` option to be enabled.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  // things just work!
  content: {
    documentDriven: true
  }
})
```

If you're not using `documentDriven` mode and your content paths are the same as their real paths,
you can enable `strictNuxtContentPaths` to get the same behaviour.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  sitemap: {
    strictNuxtContentPaths: true
  }
})
```

### Advanced: Nuxt Content App Source

If you'd like to set up a more automated Nuxt Content integration and you're not using Document Driven mode, you can add content to the sitemap as you would with [Dynamic URLs](/docs/sitemap/guides/dynamic-urls).

An example of what this might look like is below, customize to your own needs.

```ts [server/api/__sitemap__/urls.ts]
import type { ParsedContent } from '@nuxt/content/dist/runtime/types'
import { serverQueryContent } from '#content/server'
import { asSitemapUrl, defineSitemapEventHandler } from '#imports'
import { defineEventHandler } from 'h3'

export default defineSitemapEventHandler(async (e) => {
  const contentList = (await serverQueryContent(e).find()) as ParsedContent[]
  return contentList
    .filter(c => c._path.startsWith('_articles'))
    .map((c) => {
      return asSitemapUrl({
        loc: `/blog/${c._path.replace('_articles', '')}`,
        lastmod: updatedAt
      })
    })
})
```

```ts
export default defineNuxtConfig({
  sitemap: {
    sources: [
      '/api/__sitemap__/urls'
    ]
  }
})
```

## Usage

### Frontmatter `sitemap`

Use the `sitemap` key in your frontmatter to add a page to your sitemap.

You can provide any data that you would normally provide in the sitemap configuration.

#### Markdown Example

```md
---
sitemap:
  loc: /my-page
  lastmod: 2021-01-01
  changefreq: monthly
  priority: 0.8
---

# My Page
```

#### YAML Example

```yaml [content/pages/about.yml]
title: About Page
description: Learn more about us
sitemap:
  lastmod: 2025-05-13
  changefreq: monthly
  priority: 0.8
content: |
  This is the about page content
```

#### JSON Example

```json [content/products/widget.json]
{
  "title": "Widget Product",
  "price": 99.99,
  "sitemap": {
    "lastmod": "2025-05-14",
    "changefreq": "weekly",
    "priority": 0.9
  }
}
```

### Exclude from Sitemap

If you'd like to exclude a page from the sitemap, you can set `sitemap: false` in the frontmatter or `robots: false`
if you'd like to exclude it from search engines.

```md
---
sitemap: false
robots: false
---
```

#### Troubleshooting Exclusions

If `sitemap: false` or `robots: false` aren't working, check the following:

**Nuxt Content v3** — Ensure your collection schema includes `defineSitemapSchema()` in `content.config.ts`:

```ts [content.config.ts]
import { defineCollection, defineContentConfig } from '@nuxt/content'
import { defineSitemapSchema } from '@nuxtjs/sitemap/content'
import { z } from 'zod'

export default defineContentConfig({
  collections: {
    content: defineCollection({
      type: 'page',
      source: '**/*.md',
      schema: z.object({
        sitemap: defineSitemapSchema(),
      }),
    }),
  },
})
```

**Nuxt Content v2** — Ensure you have Document Driven mode or `strictNuxtContentPaths` enabled:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  content: {
    documentDriven: true
  },
  // OR
  sitemap: {
    strictNuxtContentPaths: true
  }
})
```

**Module load order** — The sitemap module must be loaded before the content module:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  modules: [
    '@nuxtjs/sitemap', // Must be before @nuxt/content
    '@nuxt/content'
  ]
})
```

If pages still appear after these checks, clear `.nuxt` and rebuild.
