Hey! The issue is that your sitemap.ts is trying to fetch dynamic data at build time, which might be failing on Vercel. Here’s how to fix it:
Option 1: Force Dynamic Rendering
Add this to the top of your sitemap.ts file to make it render at request time:
export const dynamic = 'force-dynamic'
Option 2: Add Error Handling
Wrap your data fetching in try/catch to prevent build failures:
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const domain = process.env.NEXT_PUBLIC_SITE_URL;
try {
const audioList = await getBayaanSlug();
const audioSitemap = audioList?.items?.map((audio: any) => ({
url: `${domain}/audio/${audio?.slug}`,
lastModified: audio?.sys?.publishedAt,
changeFrequency: 'yearly' as const,
priority: 0.8,
})) || [];
return [
{
url: domain || '',
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 1,
},
...audioSitemap,
];
} catch (error) {
console.error('Failed to fetch audio data for sitemap:', error);
// Return at least the homepage
return [{
url: domain || '',
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 1,
}];
}
}
Also check that your getBayaanSlug() function works correctly in production - it might need environment variables or API endpoints that aren’t available during build time.
navigating to sitemap still gives 404 page not found. I cant even see the path being logged on vercel.
I tried npm run build locally. Sitemap is working fine except on vercel
@anshumanb any idea. can it be an issue on vercel itself because you can’t even see log of the sitemap being acess.
The build logs shows sitemap but acessing gives 404. All env variables and endpoints seems to work correctly.
the runtime logs don’t show any error. It does not even detect if i tried to visit /sitemap
below you can see logs have sitemap while the deployment resources does not show sitemap
I dug into the repo and the deployed site a bit more, and this no longer looks like a dynamic-data-fetch problem.
What I found:
app/sitemap.ts exists and Vercel is recognizing it during build as ƒ /sitemap.xml
robots.txt is working fine in production
but https://www.ulama-moris.org/sitemap.xml is being served as Vercel’s /404
there’s no obvious middleware, vercel.json, rewrite, redirect, or route conflict in the repo that would explain only sitemap.xml failing
the project was also upgraded from next 14.2.35 to next 16.2.0 on April 15, 2026, which makes a framework regression feel plausible
Because of that, my strongest recommendation is to avoid the metadata file route for this case and replace:
app/sitemap.ts
with:
app/sitemap.xml/route.ts
and return the XML manually from a GET() handler.
Why I think this is the safest workaround:
it keeps the sitemap dynamic
it bypasses the Next metadata-route pipeline entirely
it gives you a normal route handler, which is much easier to debug on Vercel
So in short: I don’t think the main issue is the dynamic fetch itself anymore. I think the issue is specifically with how app/sitemap.ts is being served in production for this app/version combination.