Index of every page on this site: llms.txt

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.

The integration supports Nuxt Content v3. Nuxt Sitemap v9 removed Nuxt Content v2 support. If you use Nuxt Content v2, upgrade to Nuxt Content v3.

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

The module copies filter and onUrl into the server bundle as source. A callback can read its arguments, its own variables, and globals such as Date. It cannot read a variable or an import from the rest of content.config.ts. If a callback reads one, the build fails and names the variable. Move the value inside the callback.

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

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
export default defineNuxtConfig({
  modules: [
    '@nuxtjs/sitemap',
    '@nuxt/content' // <-- Must be after @nuxtjs/sitemap
  ]
})

Setup comark-content

comark-content is a Markdown-only content module. Nuxt Sitemap supports it first-party, with its own data source named @harlan-zw/comark-content:urls.

No schema opt in is needed. Every page collection is in the sitemap by default.

content.config.ts
import { defineCollection, defineContentConfig } from '@harlan-zw/comark-content'

export default defineContentConfig({
  collections: {
    content: defineCollection({
      type: 'page',
      source: '**/*.md',
    }),
  },
})

To keep a collection out of the sitemap, set sitemap: false on the collection.

content.config.ts
drafts: defineCollection({
  type: 'page',
  source: 'drafts/**/*.md',
  sitemap: false,
}),

The sitemap frontmatter key works the same as it does with Nuxt Content v3. See Usage.

To exclude every comark URL, add the source to excludeAppSources.

nuxt.config.ts
export default defineNuxtConfig({
  sitemap: {
    excludeAppSources: ['@harlan-zw/comark-content:urls'],
  },
})
comark-content 0.1.4 or later is required. Earlier versions add their own URLs, so pairing one with this module lists every page twice.

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:

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

# My Page

YAML example:

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:

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

lastmod from frontmatter dates

The module sets lastmod on a content page from its frontmatter dates:

  1. A sitemap.lastmod in frontmatter always wins.
  2. Otherwise the modification date: seo.articleModifiedTime, updatedAt, modifiedAt, dateModified or lastModified.
  3. Otherwise the publication date: seo.articlePublishedTime, publishedAt, datePublished or date.

A value that is not a date is skipped. The collection schema does not need to declare these keys.

---
publishedAt: 2025-03-01
updatedAt: 2025-06-12
---

This page gets <lastmod>2025-06-12</lastmod>. To read no frontmatter dates, set contentLastmod: false.

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. A robots string that contains noindex or none, such as robots: noindex, nofollow, also excludes the page. The collection schema does not need a robots field.

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

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

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.

Was this page helpful?