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?