Index of every page on this site: llms.txt
All skills
nuxt-modules avatar

/nuxtjs-sitemap

@205a027
by Nuxt Modulesnuxt-modules/sitemap441 stars
64
Run it yourself

Generate, split, and debug XML sitemaps in a Nuxt app with the @nuxtjs/sitemap module. Use when a task mentions sitemap.xml, sitemap_index.xml, the sitemap config key, defineSitemapEventHandler, dynamic sitemap URLs from a CMS or API, multiple or chunked sitemaps, zeroRuntime, hreflang in sitemaps with @nuxtjs/i18n, defineSitemapSchema for Nuxt Content, or a page that is missing from or wrongly present in the sitemap.

  • 2 files
  • 10.8 KB
  • MIT
  • Updated last month
  • GitHub
Use this Skill: https://skilld.dev/gh/nuxt-modules/sitemap/nuxtjs-sitemap

Nothing lands on disk. Nothing to clean up.

Fork this Skill

Edit a local copy. It keeps the author and licence.

SKILL.md

≈109 tokens for metadata: the name and description. ≈2.1k when used: this file. ≈500 more on demand in 1 file.

Description uses 5.5% of example budget

Before choosing a Skill, your Agent reads its name and description. All available Skills share that space.

  • A shorter description leaves more room for other Skills. This entry exceeds our 1% size suggestion.

In our Claude Code example, all Skill names and descriptions share 8,000 characters. This Skill uses ≈438 characters, or 5.5%.

The 1% threshold is a size suggestion. Longer descriptions can still fit.

Your model, settings, and other Skills decide how much text your Agent can read.

Example settings and source

The example uses a 200k-token context and default Claude Code settings. The count includes the name, description, separators, and when_to_use when present. Codex also counts local file paths.

Skit's source and limits: Codex 0.160.1, Claude Code 2.1.292.

@nuxtjs/sitemap

Use Nuxt ^4.6.0 || ^5.0.0 and Node ^22.22.3 || ^24.15.0 || >=26.0.0. The module serves /sitemap.xml, built from app pages, route rules, prerendered routes, and your sources. Docs: https://nuxtseo.com/docs/sitemap

Setup

Install with npx nuxt module add sitemap. The config key is sitemap. Included in @nuxtjs/seo v6. If the app uses @nuxtjs/seo, configure the sitemap key and do not add the module again.

Set site.url. Every <loc> resolves against it. If site.url is missing, the production server uses the request Host header. The build gives no warning. In dev, <loc> always uses the dev server host. This is expected.

If @nuxtjs/robots is installed, the module adds the sitemap to robots.txt. It uses /sitemap_index.xml when there are multiple sitemaps.

Automatic behaviour

  • Every static page is listed. Dynamic pages, such as pages/blog/[slug].vue, are not listed. Add them with a source.
  • Prerendered routes are added, including routes the prerender crawler finds.
  • A route with the robots: false route rule is dropped. So is a robots string with noindex or none.
  • When a page is prerendered, <img> and <video> inside <main> become image and video entries. article:modified_time becomes lastmod.
  • A content page gets lastmod from frontmatter: sitemap.lastmod, then a modification date (updatedAt, modifiedAt), then a publication date (publishedAt, date). contentLastmod: false turns this off.
  • Entries are sorted by path depth, then alphabetically. Set sortEntries: false to keep source order.
  • An invalid lastmod is dropped from the entry. Dev prints an XML comment in its place.
  • In production, the resolved sitemap is cached for cacheMaxAgeSeconds (600 by default). Dev and prerender do not cache.

Add dynamic URLs

Return the entries from a server route, then list the route in sources. Import defineSitemapEventHandler() from #sitemap/server. Server auto imports also resolve it. It adds types only, no cache.

// server/api/__sitemap__/urls.ts
import { defineSitemapEventHandler } from '#sitemap/server'

export default defineSitemapEventHandler(async () => {
  const posts = await $fetch<{ slug: string, updatedAt: string }[]>('https://cms.example.com/posts')
  return posts.map(post => ({
    loc: `/blog/${post.slug}`, // a path; it resolves against site.url
    lastmod: post.updatedAt,
  }))
})
// nuxt.config.ts
export default defineNuxtConfig({
  sitemap: {
    sources: ['/api/__sitemap__/urls'],
  },
})

A source can also be a remote JSON or XML URL, or [url, { headers }] for an authenticated API. If a CMS returns encoded paths, set _encoded: true on each entry to stop double encoding.

urls in the config also adds entries, but the function runs once at build time. Use sources for data that changes after deploy.

Remove or tune one page

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/checkout/**': { robots: false }, // drop from the sitemap
    '/legal': { sitemap: false }, // drop from the sitemap only
    '/about': { sitemap: { priority: 0.3, changefreq: 'yearly' } },
  },
  sitemap: {
    exclude: ['/admin/**', /^\/preview-/],
  },
})

definePageMeta({ sitemap: { priority: 0.8 } }) sets values for that page. definePageMeta({ sitemap: false }) removes it, also when it is prerendered.

Multiple sitemaps

// nuxt.config.ts
export default defineNuxtConfig({
  sitemap: {
    sitemaps: {
      pages: { includeAppSources: true, exclude: ['/blog/**'] },
      posts: { sources: ['/api/__sitemap__/posts'], chunks: 5000 },
    },
  },
})
  • The index is /sitemap_index.xml. On a server, /sitemap.xml redirects to it. A static build writes the index to /sitemap.xml as well.
  • Child sitemaps are at /__sitemap__/<name>.xml. Chunks are /__sitemap__/posts-0.xml, posts-1.xml, and so on.
  • sitemapsPathPrefix: '/' moves them to the root: /pages.xml, /posts-0.xml.
  • App sources (pages, route rules, prerender) go only to a sitemap with includeAppSources: true.
  • Top level sources also go only to sitemaps with includeAppSources: true.
  • An entry with _sitemap: 'posts' goes only to that sitemap. An unknown name logs an error and drops the entry.
  • sitemaps: true splits every URL into numbered chunks of defaultSitemapsChunkSize (1000).

Prerender and zero runtime

To prerender the sitemap, add /sitemap.xml to nitro.prerender.routes. nuxt generate does this for you. zeroRuntime: true prerenders every sitemap and removes the sitemap code from the server bundle. In both modes, sources are fetched once at build. New CMS entries do not appear until the next build.

Integrations

  • Nuxt Content v3: a collection needs defineSitemapSchema() in its schema, or it is not in the sitemap. See references/nuxt-content.md.
  • @nuxtjs/i18n: with a prefix strategy, each locale gets its own sitemap, with hreflang alternatives and x-default. The sitemap name is the locale language if it is set, else the locale code. With language: 'en-US', the path is /__sitemap__/en-US.xml. A dynamic entry goes only to the default locale sitemap. Set _i18nTransform: true to add it to every locale with its prefix. _sitemap takes the sitemap name. _sitemap: 'en' fails when the sitemap is en-US. Set autoI18n: false for one sitemap without locales.

Traps

  • String filters match whole path segments only. exclude: ['/blog/draft-*'] removes nothing. Use a RegExp such as /^\/blog\/draft-/.
  • A dynamic route is not in the sitemap until a source, urls, or the prerender crawler provides its URLs.
  • A prerendered or zeroRuntime sitemap never refetches sources. Use the runtime server for CMS data that changes between deploys.
  • Nuxt Content filter and onUrl cannot read outside variables. The build fails and names the variable. See references/nuxt-content.md.
  • lastmod set to the current date on every build tells crawlers nothing. Use a real content update time.

Version limits

v9 has these breaking changes. Each line gives the fix.

  • Nuxt ^4.6.0 || ^5.0.0 and Node ^22.22.3 || ^24.15.0 || >=26.0.0 are required. Upgrade both before the module.
  • Hook contexts receive a RequestEvent from nuxt/server. event.node.req does not exist there. Read a header with ctx.event.req.headers.get('authorization').
  • defineSitemapEventHandler() receives a RequestEvent that is also typed as the server builder's H3Event. h3 helpers and utilities typed against H3Event accept it. event.req is the web Request.
  • Import defineSitemapEventHandler() and asSitemapUrl() from #sitemap/server. Import getQuery() and other request utilities from nuxt/server.
  • @nuxtjs/robots must be v7. nuxt-site-config must be v5. Upgrade them together with the sitemap.
  • The optional zod peer is ^4.6.5. Use Zod 4 with defineSitemapSchema().
  • Nuxt Content v2 is not supported. Upgrade to Nuxt Content v3 and add defineSitemapSchema() to each collection.
  • The DevTools Sitemap tab needs the nuxtseo-devtools-host dev dependency.

Config

  • sources, urls, include, exclude, defaults: top level for one sitemap. With sitemaps, set them per sitemap.
  • excludeAppSources: true, or names such as ['nuxt:pages', 'nuxt:prerender'].
  • sitemapName (sitemap.xml): the path of the single sitemap. Ignored with sitemaps.
  • cacheMaxAgeSeconds (600): server cache and Cache-Control. false turns both off.
  • xsl (/__sitemap__/style.xsl): the browser view. Set false for raw XML. Browsers show raw i18n XML as text; that is a browser bug.
  • Other options: https://nuxtseo.com/docs/sitemap/api/config

Nitro hooks change output at runtime: sitemap:sources (add sources or request headers), sitemap:input, sitemap:resolved, sitemap:output, and sitemap:sitemaps-resolved (register sitemaps at runtime). See https://nuxtseo.com/docs/sitemap/nitro-api/nitro-hooks

Debug

  • /__sitemap__/debug.json lists every source, its URLs, and fetch errors. It exists in dev, or in production with debug: true. zeroRuntime removes it.
  • Nuxt DevTools has a Sitemap tab with the same data. The tab needs nuxtseo-devtools-host as a dev dependency: pnpm add -D nuxtseo-devtools-host.
  • For a prerendered sitemap, set debug: true and read .output/public/__sitemap__/debug.json.

Source: SKILL.md on GitHub

skilld matched fixed text patterns in SKILL.md and file names. Patterns miss obfuscated code.

skilld run checks every file with the same patterns. It asks for approval before it loads a Skill with a behavior marked Needs approval.

No third-party reports yet.

Signed by skilld at 205a027. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 3 weeks ago.

Activeupdated last month
Other metadata
compatibility
Requires Node.js ^22.22.3 || ^24.15.0 || >=26.0.0. Requires Nuxt ^4.6.0 || ^5.0.0.

README badge

README badge for nuxt-modules/sitemap