Next.js 14 App Router - Generate custom sitemap XML & Prismic pages- Not working

Hello, I am trying to create a sitemap xml through a sitemap.ts file as mentioned in the documentation: Metadata Files: sitemap.xml | Next.js

Back with pages router, it was working fine. Now moved to App Router in a new app, not working.

I have been trying multiple variation, but no sitemap xml get generated. The thing is that, unlike the very basic example in next js doc, I have some pages on Prismic, other in my repo. Hence, I've tried this code, in vain:

import { MetadataRoute } from 'next'
import fetchAllTypesPages from '@/utils/fetchAllTypesPages'
import { createClient } from '@/prismicio'

// Ensure you have SITE_URL defined in your environment variables
const siteUrl = process.env.SITE_URL || 'https://guadeloupeloc.fr/' // Fallback in case it's not defined

type ChangeFrequency =
  | 'always'
  | 'hourly'
  | 'daily'
  | 'weekly'
  | 'monthly'
  | 'yearly'
  | 'never'

interface Route {
  url: string
  lastModified: Date
  changeFrequency: ChangeFrequency
  priority: number
}

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const client = createClient()

  // Fetch all static and dynamic routes
  const pages = await fetchAllTypesPages(client)

  return pages.map((page) => ({
    url: `${siteUrl}${page.url}`,
    lastModified: new Date(),
    changeFrequency: 'weekly',
    priority: 0.7
  }))
}

Thanks for the help!

PS: I've tried also the old version as renaming sitemap.ts to sitemap.xml.js as stated here: XML Sitemaps - Crawling and Indexing | Learn Next.js

Not working neither. Not seeing any sitemap.xml being created, and when I hit it I get this error:

Application error: a server-side exception has occurred (see the server logs for more information).

Digest: 4204100638
And server errors:
[Error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.] {
digest: '4204100638'
}

Don’t judge my less-than-elegant and certainly-not-dry but functional example

// src/app/sitemap.ts
import { createClient } from '@/prismicio'
import { asDate } from '@prismicio/client'
export default async function sitemap() {
  const client = createClient()
  const settings = await client.getSingle('settings')
  const pages = await client.getAllByType('page')
  const sitemapPages = pages.map(page => ({
    url: `https://${settings.data.domain || `example.com`}${page.url}`,
    lastModified: asDate(page.last_publication_date),
  }))
  const homepage = await client.getSingle('homepage')
  const sitemapHomepage = {
    url: `https://${settings.data.domain || `example.com`}${homepage.url}`,
    lastModified: asDate(homepage.last_publication_date),
  }
  const posts = await client.getAllByType('post')
  const sitemapPosts = posts.map(post => ({
    url: `https://${settings.data.domain || `example.com`}${post.url}`,
    lastModified: asDate(post.last_publication_date),
  }))
  const projects = await client.getAllByType('project')
  const sitemapPortfolios = projects.map(project => ({
    url: `https://${settings.data.domain || `example.com`}${project.url}`,
    lastModified: asDate(project.last_publication_date),
  }))

  return [
    sitemapHomepage,
    ...sitemapPages,
    ...sitemapPosts,
    ...sitemapPortfolios,
  ]
}
1 Like

Awesome @nf_mastroianni!
Thanks for the help.

My sitemap.ts ended up working after all with the following version :D

import { MetadataRoute } from 'next'
import fetchAllTypesPages from '@/utils/fetchAllTypesPages'
import { createClient } from '@/prismicio'

const baseUrl = process.env.SITE_URL || 'https://guadeloupeloc.fr'

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const client = createClient()

  // Fetch dynamic pages from Prismic
  const dynamicPages = await fetchAllTypesPages(client)

  // Correctly map dynamic pages to the expected format
  const dynamicRoutes = dynamicPages.map((page) => ({
    url: `${baseUrl}${page.url}`, // Use 'url' instead of 'loc'
    lastModified: new Date().toISOString()
  }))

  // Static routes directly added to the sitemap
  const staticRoutes: MetadataRoute.Sitemap = [
    {
      url: 'https://guadeloupeloc.fr',
      lastModified: new Date().toISOString()
      // Optionally: change frequency & priority here
    }
    // Add more static routes as needed
  ]

  return [...staticRoutes, ...dynamicRoutes]
}

2 Likes