---
title: "Nuxt Content · Nuxt Sitemap · Nuxt SEO"
canonical_url: "https://nuxtseo.com/docs/sitemap/guides/content"
last_updated: "2026-08-15T17:56:02.512Z"
meta:
  description: "How to use the Nuxt Sitemap module with Nuxt Content."
  "og:description": "How to use the Nuxt Sitemap module with Nuxt Content."
  "og:title": "Nuxt Content · Nuxt Sitemap · Nuxt SEO"
---

Nuxt SEO on GitHub

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

**Core Concepts**

# **Nuxt Content**

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.

content.config.ts

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

content.config.ts

```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
          },
        }),
      }),
    }),
  },
})
```

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.

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:

content.config.ts

```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
    },
  }),
})
```

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

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

nuxt.config.ts

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

nuxt.config.ts

```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 behavior.

nuxt.config.ts

```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~~**](https://nuxtseo.com/docs/sitemap/guides/dynamic-urls).

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

server/api/\_\_sitemap\_\_/urls.ts

```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
      })
    })
})
```

nuxt.config.ts

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

content/pages/about.yml

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

content/products/widget.json

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

content.config.ts

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

nuxt.config.ts

```ts
export default defineNuxtConfig({
  content: {
    documentDriven: true
  },
  // OR
  sitemap: {
    strictNuxtContentPaths: true
  }
})
```

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

nuxt.config.ts

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

**Was this page helpful?**

### **Related **

[**Dynamic URL Endpoints**](https://nuxtseo.com/docs/sitemap/guides/dynamic-urls)

[**Data Sources**](https://nuxtseo.com/docs/sitemap/getting-started/data-sources)

[**Lastmod, Priority, and Changefreq**](https://nuxtseo.com/docs/sitemap/advanced/loc-data)

[**I18n** Setting up a sitemap with Nuxt I18n and Nuxt I18n Micro.](https://nuxtseo.com/docs/sitemap/guides/i18n) [**Nuxt Prerendering** Prerender your pages and have them all automatically added to your sitemap.](https://nuxtseo.com/docs/sitemap/guides/prerendering)