import { queryCollection } from '@nuxt/content/server' import { inferSiteURL } from '../../utils/meta' import { getAvailableLocales, getCollectionsToQuery, isNavigationPath } from '../utils/content' interface SitemapUrl { loc: string lastmod?: string } export default defineEventHandler(async (event) => { const config = useRuntimeConfig(event) const siteUrl = inferSiteURL() || '' const availableLocales = getAvailableLocales(config.public as Record) const collections = getCollectionsToQuery(undefined, availableLocales) if (availableLocales.length > 0) { for (const locale of availableLocales) { collections.push(`landing_${locale}`) } } else { collections.push('landing') } const urls: SitemapUrl[] = [] for (const collection of collections) { try { const pages = await (queryCollection as unknown as ( event: unknown, collection: string, ) => { all: () => Promise & { path?: string }>> })(event, collection).all() for (const page of pages) { const meta = page.meta as Record const pagePath = page.path || '/' // Skip pages with sitemap: false in frontmatter if (meta.sitemap === false) continue // Skip .navigation files (used for navigation configuration) if (isNavigationPath(pagePath)) continue const urlEntry: SitemapUrl = { loc: pagePath, } // Add lastmod if available (modifiedAt from content) if (meta.modifiedAt && typeof meta.modifiedAt === 'string') { urlEntry.lastmod = meta.modifiedAt.split('T')[0] // Use date part only (YYYY-MM-DD) } urls.push(urlEntry) } } catch { // Collection might not exist, skip it } } const sitemap = generateSitemap(urls, siteUrl) setResponseHeader(event, 'content-type', 'application/xml') return sitemap }) function generateSitemap(urls: SitemapUrl[], siteUrl: string): string { const urlEntries = urls .map((url) => { const loc = siteUrl ? `${siteUrl}${url.loc}` : url.loc let entry = ` \n ${escapeXml(loc)}` if (url.lastmod) { entry += `\n ${escapeXml(url.lastmod)}` } entry += `\n ` return entry }) .join('\n') return ` ${urlEntries} ` } function escapeXml(str: string): string { return str .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, ''') }