---
title: "How to Generate a Sitemap in Nuxt"
description: "Generate an XML sitemap in Nuxt with the Sitemap module or a Nitro route, then get Google to actually crawl it."
canonical_url: "https://nuxtseo.com/learn-seo/nuxt/controlling-crawlers/sitemaps"
last_updated: "2026-07-16"
---

<key-takeaways>

- Sitemaps limited to 50,000 URLs or 50MB. Use sitemap index for larger sites
- Skip `changefreq` and `priority`. Google ignores them, only `lastmod` matters
- Nuxt Sitemap module auto-generates from pages/ and handles large sites

</key-takeaways>

This guide covers sitemap strategy and configuration. For module installation and API reference, see the [Nuxt Sitemap documentation](/docs/sitemap/getting-started/introduction).

The `sitemap.xml` file helps search engines discover your pages. Google considers sites "small" if they have [500 pages or fewer](https://developers.google.com/search/docs/crawling-indexing/sitemaps/overview). You likely need a sitemap if you exceed this, have new sites with few backlinks, or update content frequently. For new sites, pair your sitemap with a solid [internal linking structure](/learn-seo/nuxt/routes-and-rendering/internal-linking) and a [pre-launch warmup](/learn-seo/pre-launch-warmup) strategy to accelerate discovery.

## Static Sitemap

For small sites under 100 pages, create a static sitemap in your public directory:

```dir
public/
  sitemap.xml
```

Add your URLs with proper formatting:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://mysite.com/</loc>
    <lastmod>2024-11-03</lastmod>
  </url>
  <url>
    <loc>https://mysite.com/about</loc>
    <lastmod>2024-12-10</lastmod>
  </url>
</urlset>
```

Sitemaps are limited to [50,000 URLs or 50MB uncompressed](https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap). Use UTF-8 encoding and absolute URLs only.

## Dynamic Generation

For sites with frequently changing content (e-commerce, blogs, news) or [programmatic SEO](/learn-seo/nuxt/routes-and-rendering/programmatic-seo) pages, generate sitemaps server-side with a Nitro route:

```ts [server/routes/sitemap.xml.ts]
export default defineEventHandler(async (event) => {
  const pages = await fetchAllPages()

  const urls = pages.map(page => `
  <url>
    <loc>https://mysite.com${page.path}</loc>
    <lastmod>${page.updatedAt}</lastmod>
  </url>`).join('\n')

  const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${urls}
</urlset>`

  setHeader(event, 'Content-Type', 'application/xml')
  return sitemap
})
```

This runs on every request. For better performance, use the Sitemap module which caches and optimizes sitemap generation.

## Automatic Generation

Nuxt generates sitemaps automatically with the Sitemap module:

<module-card slug="sitemap">



</module-card>

Install and configure:

```bash
npx nuxi@latest module add sitemap
```

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  modules: ['@nuxtjs/sitemap'],
  site: {
    url: 'https://mysite.com'
  }
})
```

This creates a sitemap from your routes automatically. For static sites, it's generated at build time. For dynamic sites, it's generated on request.

The module handles:

- Route discovery from `pages/` directory
- Dynamic routes with route rules
- Sitemap indexes for large sites
- Image and video sitemaps
- News sitemaps
- Multi-language sitemaps

For full configuration options, see the [Sitemap module docs](/docs/sitemap/getting-started/introduction).

## XML Sitemap Tags

A basic sitemap uses these elements:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://mysite.com/page</loc>
    <lastmod>2024-11-03</lastmod>
  </url>
</urlset>
```

<table>
<thead>
  <tr>
    <th>
      Tag
    </th>
    
    <th>
      Status
    </th>
    
    <th>
      Google Uses?
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code className="language-html shiki shiki-themes github-light github-light material-theme-palenight" language="html" style="">
        <span class="sx-uw">
          <
        </span>
        
        <span class="sFfpx">
          loc
        </span>
        
        <span class="sx-uw">
          >
        </span>
      </code>
    </td>
    
    <td>
      Required
    </td>
    
    <td>
      Yes, the page URL
    </td>
  </tr>
  
  <tr>
    <td>
      <code className="language-html shiki shiki-themes github-light github-light material-theme-palenight" language="html" style="">
        <span class="sx-uw">
          <
        </span>
        
        <span class="sFfpx">
          lastmod
        </span>
        
        <span class="sx-uw">
          >
        </span>
      </code>
    </td>
    
    <td>
      Recommended
    </td>
    
    <td>
      Yes, <a href="https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap" rel="nofollow">
        if consistently accurate
      </a>
    </td>
  </tr>
  
  <tr>
    <td>
      <code className="language-html shiki shiki-themes github-light github-light material-theme-palenight" language="html" style="">
        <span class="sx-uw">
          <
        </span>
        
        <span class="sFfpx">
          changefreq
        </span>
        
        <span class="sx-uw">
          >
        </span>
      </code>
    </td>
    
    <td>
      Skip
    </td>
    
    <td>
      <a href="https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap" rel="nofollow">
        No, Google ignores this
      </a>
    </td>
  </tr>
  
  <tr>
    <td>
      <code className="language-html shiki shiki-themes github-light github-light material-theme-palenight" language="html" style="">
        <span class="sx-uw">
          <
        </span>
        
        <span class="sFfpx">
          priority
        </span>
        
        <span class="sx-uw">
          >
        </span>
      </code>
    </td>
    
    <td>
      Skip
    </td>
    
    <td>
      <a href="https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap" rel="nofollow">
        No, Google ignores this
      </a>
    </td>
  </tr>
</tbody>
</table>

Google only uses `<lastmod>` [if it's consistently and verifiably accurate](https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap), meaning it can compare the date against the page's actual last modification. Update it when you change main content, structured data, or links: a copyright year bump or a typo fix doesn't count. Sitemaps that fake the date lose Google's trust in the whole file.

## IndexNow: Push-Based Discovery

Sitemaps are pull-based: crawlers check them on their own schedule. [IndexNow](https://www.indexnow.org/) is push-based. It's a protocol that notifies search engines the moment you create, update, or delete a page, instead of making them wait to rediscover it on the next crawl. Without it, [discovery can take days to weeks](https://www.indexnow.org/); Bing, Yandex, Seznam, Naver, and Yep all support it. Google does not.

The [Nuxt Sitemap module](/docs/sitemap/getting-started/introduction) supports IndexNow by default.

## Sitemap Index for Large Sites

If you exceed 50,000 URLs or 50MB, [split your sitemap into multiple files](https://developers.google.com/search/docs/crawling-indexing/sitemaps/large-sitemaps):

```xml [sitemap-index.xml]
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <sitemap>
    <loc>https://mysite.com/sitemap-products.xml</loc>
    <lastmod>2024-11-03</lastmod>
  </sitemap>
  <sitemap>
    <loc>https://mysite.com/sitemap-blog.xml</loc>
    <lastmod>2024-12-10</lastmod>
  </sitemap>
</sitemapindex>
```

Submit the index file to [Google Search Console](/learn-seo/nuxt/launch-and-listen/search-console) and it will crawl every sitemap listed inside it.

The Sitemap module handles this automatically when your site exceeds limits.

## Specialized Sitemaps

### News Sitemap

News publishers should create [separate news sitemaps](https://developers.google.com/search/docs/crawling-indexing/sitemaps/news-sitemap) with articles from the last 2 days:

```xml [sitemap-news.xml]
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">
  <url>
    <loc>https://mysite.com/article</loc>
    <news:news>
      <news:publication>
        <news:name>Site Name</news:name>
        <news:language>en</news:language>
      </news:publication>
      <news:publication_date>2024-12-10T12:00:00+00:00</news:publication_date>
      <news:title>Article Title</news:title>
    </news:news>
  </url>
</urlset>
```

Remove articles older than 2 days to keep the sitemap fresh; don't create new sitemaps daily, update the existing one.

### Image Sitemap

For galleries or image-heavy sites, add image metadata:

```xml [sitemap.xml]
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
  <url>
    <loc>https://mysite.com/page</loc>
    <image:image>
      <image:loc>https://mysite.com/image.jpg</image:loc>
      <image:title>Image Title</image:title>
    </image:image>
  </url>
</urlset>
```

[Image sitemaps help Google find images loaded via JavaScript](https://developers.google.com/search/docs/crawling-indexing/sitemaps/image-sitemaps) or not directly linked in HTML.

## Submit to Google Search Console

After generating your sitemap, [submit it to Google Search Console](https://support.google.com/webmasters/answer/7451001):

1. [Verify site ownership](/learn-seo/nuxt/launch-and-listen/search-console) (DNS, HTML file upload, or Google Analytics)
2. Navigate to **Sitemaps** under **Indexing**
3. Enter your sitemap URL: `https://mysite.com/sitemap.xml`
4. Click **Submit**

Google processes the sitemap and reports status:

- **Success**: sitemap accepted, pages discovered
- **Pending**: processing in progress
- **Couldn't fetch**: URL wrong or blocked by robots.txt

Check the Sitemaps report for coverage stats, indexing errors, and discovered URLs.

### Before Submitting

Validate your sitemap:

- XML syntax is valid (use an [online validator](https://www.xml-sitemaps.com/validate-xml-sitemap.html))
- All URLs return 200 status (not 404 or 500)
- URLs match [canonical URLs](/learn-seo/nuxt/controlling-crawlers/canonical-urls) exactly
- `<lastmod>` dates are accurate
- File uses UTF-8 encoding

### Alternative Submission

Reference your sitemap in `robots.txt`:

```txt [public/robots.txt]
User-agent: *
Allow: /

Sitemap: https://mysite.com/sitemap.xml
```

Google discovers this automatically when [crawling your robots.txt](/learn-seo/nuxt/controlling-crawlers/robots-txt).

### Troubleshooting "Couldn't Fetch"

Search Console sometimes shows **"Couldn't fetch"** or **"Sitemap could not be read"** even though the sitemap validates and loads fine in a browser. [Google lists several causes](https://support.google.com/webmasters/answer/7451001) for this status: the sitemap is blocked by `robots.txt`, the URL is wrong (a 404), the site has an unresolved manual action, or the fetch simply failed.

1. **Rule out the obvious first.** Confirm the sitemap URL loads directly, isn't blocked in `robots.txt`, and your site has no pending manual action.
2. **Use the URL Inspection tool** in Search Console. Paste your sitemap URL and click **Live test**. If Page fetch shows "Successful" and Crawl allowed shows "Yes", the sitemap itself is fine and the error is transient.
3. **Give it time.** Google says some fetch errors are transient and resolve on later crawl attempts, so wait and check back rather than resubmitting immediately.

If the error persists after checking the above:

- **Remove and resubmit**. Delete the sitemap from Search Console, then resubmit it. This forces Google to re-fetch from scratch.
- **Change the sitemap URL**. If resubmission doesn't work, rename the sitemap path (for example, from `/sitemap.xml` to `/sitemap_index.xml` using the `sitemapName` option in the Sitemap module). Google treats this as a new sitemap and re-fetches it on its next crawl.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  sitemap: {
    sitemapName: 'sitemap_index.xml'
  }
})
```

<callout type="info">

This issue is especially common with sitemap indexes that contain multiple child sitemaps (for example, one per locale). Google may fetch some children successfully while others stay stuck. The same workarounds apply: wait, then resubmit or rename if needed.

</callout>

## Checklist

<checklist id="nuxt-sitemaps">

- Sitemap includes every indexable URL, none blocked by `robots.txt` or `noindex`
- `<lastmod>` dates are accurate, not blanket-set on every deploy
- Sitemap stays under 50,000 URLs and 50MB, split into an index if not
- Sitemap submitted in Google Search Console and referenced in `robots.txt`
- Large or multi-locale sites use the Sitemap module's automatic indexing

</checklist>
