Sitemap
Guides

Dynamic URL Endpoint

Use runtime API endpoints to generate dynamic URLs for your sitemap.

In some instances, like using a CMS, you may need to implement an endpoint to make all of your site URLs visible to the module.

To do this, you can provide user sources to the module.

Dynamic URLs from an external API

Fetching from an external API

When you have a source that is a third-party API returning dynamic URLs,then you have a couple of options.

  1. Add the endpoint directly to the sources config - Good for endpoints that return the data already in the correct format
  2. Make an API endpoint that returns the URLs - Required when you have to transform the data or implement your own caching

1. Using sources config

If the URL you're fetching from requires any extra headers to work, you can provide a source as an array, where the second option is the fetch options.

nuxt.config.ts
export default defineNuxtConfig({
  sitemap: {
    sources: [
      // fetch from an unauthenticated endpoint
      'https://api.example.com/pages/urls',
      // fetch from an authenticated endpoint
      [
        'https://authenticated-api.example.com/pages/urls',
        { headers: { Authorization: 'Bearer <token>' } } // fetch options
      ]
    ]
  }
})

2. Create your own endpoint

  1. Create a new API endpoint

In this code snippet we're using the defineSitemapEventHandler helper to create a new API endpoint. This is a simple wrapper for defineEventHandler that forces the TypeScript types.

// server/api/__sitemap__/urls.ts
export default defineSitemapEventHandler(() => {
  return [
    {
      loc: '/about-us',
      // will end up in the pages sitemap
      _sitemap: 'pages',
    }
  ]
})

To solve type issues you have in using defineSitemapEventHandler, you can use the asSitemapUrl composable.

server/api/__sitemap__/urls.ts
import { asSitemapUrl, defineSitemapEventHandler } from '#imports'

export default defineSitemapEventHandler(async () => {
  // fetch data directly in the correct type
  const posts = await $fetch<ReturnType<typeof asSitemapUrl>>('/api/posts')
  const pages = await $fetch<{ pages: { slug: string, title: string } }>('/api/posts')
  return [
    ...posts,
    // map URLS as needed
    ...pages.map(p => asSitemapUrl({
      loc: p.slug,
    }))
  ]
})

If you still have TypeScript errors, you should just use defineEventHandler.

  1. Add the endpoint to your nuxt.config.ts
export default defineNuxtConfig({
  sitemap: {
    sources: [
      '/api/__sitemap__/urls',
    ]
  }
})