Fix Your Sitemap for Nuxt

Updated April 2026·By SitemapFixer Team

Nuxt 3 uses the @nuxtjs/sitemap module to generate sitemap.xml. Dynamic route params, server routes, and @nuxtjs/i18n integration often need explicit configuration or the sitemap ships with only the static pages.

Analyze your Nuxt sitemap nowTry Sitemap Fixer Free

Nuxt 3 has a really solid sitemap story via @nuxtjs/sitemap - better than what's in Next.js core, honestly. But it assumes you'll wire up your content source. The module can see pages/*.vue automatically. It can't see your Nuxt Content markdown files, your Strapi API, or your Supabase rows unless you tell it.

Reviewed a Nuxt 3 marketing site with 2,100 blog posts stored in Nuxt Content. The sitemap listed 8 URLs - just the static pages. The dev had installed @nuxtjs/sitemap, pointed site.url at production, and shipped. Nobody had written the sources config, so dynamic routes were invisible. A 20-line server/api/__sitemap__/urls.ts fixed it.

Working nuxt.config.ts

export default defineNuxtConfig({
  modules: ['@nuxtjs/sitemap', '@nuxtjs/i18n'],

  site: {
    url: 'https://example.com',
  },

  sitemap: {
    sources: ['/api/__sitemap__/urls'],
    exclude: ['/admin/**', '/dashboard/**', '/preview/**'],
    autoI18n: true,
    defaults: {
      changefreq: 'weekly',
      priority: 0.7,
    },
  },

  routeRules: {
    '/admin/**': { robots: 'noindex' },
    '/api/**': { robots: 'noindex' },
  },

  i18n: {
    locales: [
      { code: 'en', language: 'en-US' },
      { code: 'de', language: 'de-DE' },
    ],
    defaultLocale: 'en',
  },
});

Dynamic routes via server API

// server/api/__sitemap__/urls.ts
import { serverQueryContent } from '#content/server';

export default defineSitemapEventHandler(async (event) => {
  const posts = await serverQueryContent(event, 'blog')
    .where({ _draft: false, published: { $lte: new Date() } })
    .find();

  return posts.map((p) => ({
    loc: `/blog/${p._path.replace('/blog/', '')}`,
    lastmod: p.updatedAt,
    changefreq: 'weekly',
    priority: 0.7,
  }));
});

Common Nuxt Sitemap Issues

i18n handling

With autoI18n: true, the sitemap module picks up your i18n locales automatically and emits xhtml:link alternates inside each URL entry. Verify the output by requesting /sitemap.xml and looking for the xhtml:link tags. If they're missing, check that @nuxtjs/i18n is listed before @nuxtjs/sitemap in the modules array - order matters for module detection.

Step-by-Step Fix Guide

  1. Install with npx nuxi module add sitemap
  2. Set site.url to production at the top level of nuxt.config.ts
  3. Create server/api/__sitemap__/urls.ts for dynamic routes
  4. Set sitemap.sources to include your API handler
  5. Add exclude patterns for admin, dashboard, preview
  6. Enable autoI18n: true if using @nuxtjs/i18n
  7. Use routeRules or defineRouteRules for noindex on private pages
  8. Verify with curl https://yoursite.com/sitemap.xml
  9. Submit to Google Search Console

Frequently Asked Questions

How do I add dynamic routes to a Nuxt sitemap?
Create a server route at server/api/__sitemap__/urls.ts that returns your slugs, then add sources: ['/api/__sitemap__/urls'] in the sitemap config. The module fetches those URLs at build time and merges them in.
Does @nuxtjs/sitemap work with SSR routes?
Yes, but only if you list them explicitly through sources or urls. The module can't introspect which SSR routes exist - you have to tell it. Static pages/ and prerendered routes are detected automatically.
How do I exclude private routes from a Nuxt sitemap?
Use defineRouteRules({ sitemap: false }) in the page component, or set routeRules in nuxt.config.ts to apply noindex to patterns like '/dashboard/**'.
Analyze your Nuxt sitemap
Find all issues in your sitemap - free, no credit card needed
Analyze My Sitemap Free
Other platform guides