Guides
Dynamic URL Endpoints
 Last updated  by 
Harlan Wilton
 in doc: wordpress example. Introduction
When working with a CMS or external data sources, you may need to generate sitemap URLs dynamically at runtime.
The module supports two types of data sources:
- JSON responses from API endpoints
 - XML sitemaps from external sources
 
Using External XML Sitemaps
If you have an existing XML sitemap, you can reference it directly in your configuration:
nuxt.config.ts
export default defineNuxtConfig({
  sitemap: {
    sources: [
      'https://example.com/sitemap.xml',
    ]
  }
})
Dynamic URLs from External APIs
When fetching dynamic URLs from external APIs, you have two main approaches:
- Direct source configuration - Use when the API returns data in the correct format
 - Custom API endpoint - Use when you need to transform data or implement caching
 
1. Using Source Configuration
For APIs that require authentication or custom headers, provide sources as an array with fetch options:
nuxt.config.ts
export default defineNuxtConfig({
  sitemap: {
    sources: [
      // Unauthenticated endpoint
      'https://api.example.com/pages/urls',
      // Authenticated endpoint
      [
        'https://authenticated-api.example.com/pages/urls',
        { headers: { Authorization: 'Bearer <token>' } }
      ]
    ]
  }
})
2. Creating Custom Endpoints
Step 1: Create the API endpoint
Use the defineSitemapEventHandler helper to create type-safe sitemap endpoints:
// server/api/__sitemap__/urls.ts
import { defineSitemapEventHandler } from '#imports'
import type { SitemapUrlInput } from '#sitemap/types'
export default defineSitemapEventHandler(() => {
  return [
    {
      loc: '/about-us',
      // Specify which sitemap this URL belongs to
      _sitemap: 'pages',
    },
  ] satisfies SitemapUrlInput[]
})
// server/api/__sitemap__/urls.ts
import { defineSitemapEventHandler } from '#imports'
import type { SitemapUrl } from '#sitemap/types'
export default defineSitemapEventHandler(async () => {
  const [posts, pages] = await Promise.all([
    $fetch<{ path: string, slug: string }[]>('https://api.example.com/posts')
      .then(posts => posts.map(p => ({
        loc: `/blog/${p.slug}`, // Transform to your domain structure
        _sitemap: 'posts',
      } satisfies SitemapUrl))),
    $fetch<{ path: string }[]>('https://api.example.com/pages')
      .then(pages => pages.map(p => ({
        loc: p.path,
        _sitemap: 'pages',
      } satisfies SitemapUrl))),
  ])
  return [...posts, ...pages]
})
// server/api/__sitemap__/wordpress.ts
import { defineSitemapEventHandler } from '#imports'
export default defineSitemapEventHandler(async () => {
  const posts = await $fetch('https://api.externalwebsite.com/wp-json/wp/v2/posts')
  
  return posts.map(post => ({
    // Transform external URL to your domain
    loc: `/blog/${post.slug}`, // NOT post.link
    lastmod: post.modified,
    changefreq: 'weekly',
    priority: 0.7,
  }))
})
// server/api/__sitemap__/urls.ts
import { defineSitemapEventHandler } from '#imports'
import type { SitemapUrl } from '#sitemap/types'
export default defineSitemapEventHandler(async () => {
  const config = useRuntimeConfig()
  const baseUrl = config.public.siteUrl
  const locales = config.public.i18n.locales.map(locale => locale.code)
  const isoLocales = Object.fromEntries(
    config.public.i18n.locales.map(locale => ([locale.code, locale.iso]))
  )
  // Example: Fetch data for each locale
  const apiQueries = locales.map(locale => 
    $fetch(`${config.public.apiEndpoint}/sitemap/${locale}/products`)
  )
  const sitemaps = await Promise.all(apiQueries)
  
  return sitemaps.flat().map(entry => ({
    // explicit sitemap mapping
    _sitemap: isoLocales[entry.locale],
    loc: `${baseUrl}/${entry.locale}/product/${entry.url}`,
    alternatives: entry.alternates?.map(alt => ({
      hreflang: isoLocales[alt.locale],
      href: `${baseUrl}/${alt.locale}/product/${alt.url}`
    }))
  } satisfies SitemapUrl))
})
Ensure you have a 
server/tsconfig.json file for proper TypeScript type support.Step 2: Configure the endpoint
Add your custom endpoint to the sitemap configuration:
export default defineNuxtConfig({
  sitemap: {
    sources: [
      '/api/__sitemap__/urls',
    ]
  }
})
export default defineNuxtConfig({
  sitemap: {
    sitemaps: {
      posts: {
        sources: [
          '/api/__sitemap__/urls/posts',
        ]
      },
      pages: {
        sources: [
          '/api/__sitemap__/urls/pages',
        ]
      }
    }
  }
})
 Did this page help you?