diff --git a/next.config.ts b/next.config.ts index 31d3ca9b..e51c52f0 100644 --- a/next.config.ts +++ b/next.config.ts @@ -53,6 +53,17 @@ const nextConfig: NextConfig = { // pin it so a future Next minor that flips defaults can't silently // split bench rankings between the two surface URLs. trailingSlash: false, + // Inject a build-time timestamp so the sitemap can emit a stable + // per deploy instead of `new Date()` at request time. The + // sitemap runs on force-dynamic (to bypass Next's 2 MB Data Cache + // limit), which means `new Date()` at module init evaluates anew on + // every Google crawl. Result: every URL in the sitemap got a freshly + // updated lastmod each visit, Google flagged the signal as unreliable + // and stopped using it to prioritise recrawls. This baking pins the + // value at build time so it changes only when a new deploy ships. + env: { + NEXT_PUBLIC_BUILD_TIME: new Date().toISOString(), + }, turbopack: { root: __dirname, }, diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts index 403a05ba..aed5a6df 100644 --- a/src/app/sitemap.ts +++ b/src/app/sitemap.ts @@ -32,7 +32,15 @@ import type { Answer } from "@/lib/answers"; // succeeds; the next ISR refresh recovers automatically. export const dynamic = "force-dynamic"; -const BUILD_TIME = new Date(); +// Stable per deploy, not per request. process.env.NEXT_PUBLIC_BUILD_TIME +// is injected in next.config.ts at build time. Falling back to new Date() +// keeps local dev working. Critical: must NOT be `new Date()` at request +// time because the sitemap runs on force-dynamic (see header comment) so +// every Google crawl would otherwise see a fresh lastmod on every URL +// and Google would discard the signal as unreliable sitewide. +const BUILD_TIME = process.env.NEXT_PUBLIC_BUILD_TIME + ? new Date(process.env.NEXT_PUBLIC_BUILD_TIME) + : new Date(); // Vercel's build container doesn't preserve git-checkout mtimes — every // file gets reset to the build-system default (Oct 20 2018), which leaks // into the sitemap as `2018-10-20T...` for editorial