Skip to content

Commit 0bcb0ad

Browse files
Marv51claude
andcommitted
Serve sitemap via a resource route and make the drift check fatal
Move sitemap generation from the buildEnd hook into a resource route (app/routes/sitemap.tsx) whose loader returns renderSitemap() as application/xml. It still prerenders to build/client/sitemap.xml and now also serves live under `npm run dev`, at the cost of a sitemap.xml.data sidecar and a tiny client chunk. The prerender hook keeps the getStaticPaths() cross-check but now throws instead of warning, so a prerendered page missing from both PAGES and the exclude list fails the build. /sitemap.xml is added to the exclude list since the resource route makes it a discovered path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent abe024c commit 0bcb0ad

3 files changed

Lines changed: 19 additions & 14 deletions

File tree

src/app/routes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export default [
55
route("/Project-Quick-Open/datenschutz.html", "routes/project-quick-privacy.tsx"),
66
route("/SWR3App/datenschutz.html", "routes/swr3-app-privacy.tsx"),
77
route("404", "routes/not-found.tsx", { "index": true}),
8+
route("sitemap.xml", "routes/sitemap.tsx"),
89
layout("routes/layout.tsx", [
910
index("routes/home.tsx"),
1011
...prefix("en", [

src/app/routes/sitemap.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { renderSitemap } from "../seo-links";
2+
3+
// Resource route (loader only, no component): prerendered to
4+
// build/client/sitemap.xml, and also served live under `npm run dev`.
5+
export function loader() {
6+
return new Response(renderSitemap(), {
7+
headers: { "Content-Type": "application/xml" },
8+
});
9+
}

src/react-router.config.ts

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,33 @@
11
import type { Config } from "@react-router/dev/config";
2-
import { writeFile } from "node:fs/promises";
3-
import { join } from "node:path";
4-
import { renderSitemap, sitemapPaths } from "./app/seo-links";
2+
import { sitemapPaths } from "./app/seo-links";
53

6-
// Prerendered paths intentionally kept OUT of the sitemap: the error page and
7-
// the two standalone app privacy policies (not part of the bilingual site).
4+
// Prerendered paths intentionally kept OUT of the sitemap: the error page, the
5+
// sitemap resource route itself, and the two standalone app privacy policies
6+
// (not part of the bilingual site).
87
const SITEMAP_EXCLUDED = new Set([
98
"/404",
9+
"/sitemap.xml",
1010
"/Project-Quick-Open/datenschutz.html",
1111
"/SWR3App/datenschutz.html",
1212
]);
1313

1414
export default {
1515
ssr: false,
1616
// Function form of `prerender` returns the same static paths as `true`, but
17-
// also lets us cross-check route discovery against the sitemap so a new page
18-
// can't silently go missing from it.
17+
// also lets us cross-check route discovery against the sitemap. A prerendered
18+
// page missing from both PAGES and the exclude list fails the build, so the
19+
// sitemap can't silently fall out of sync with the routes.
1920
prerender: ({ getStaticPaths }) => {
2021
const discovered = getStaticPaths();
2122
const known = new Set([...sitemapPaths(), ...SITEMAP_EXCLUDED]);
2223
const unaccounted = discovered.filter((path) => !known.has(path));
2324
if (unaccounted.length > 0) {
24-
console.warn(
25+
throw new Error(
2526
`[sitemap] Prerendered path(s) missing from the sitemap and exclude ` +
2627
`list: ${unaccounted.join(", ")}. Add them to PAGES in ` +
2728
`app/seo-links.ts, or to SITEMAP_EXCLUDED in react-router.config.ts.`,
2829
);
2930
}
3031
return discovered;
3132
},
32-
// Emit sitemap.xml into the prerendered output, derived from PAGES.
33-
buildEnd: async ({ reactRouterConfig }) => {
34-
const out = join(reactRouterConfig.buildDirectory, "client", "sitemap.xml");
35-
await writeFile(out, renderSitemap(), "utf-8");
36-
console.log(`[sitemap] wrote ${out}`);
37-
},
3833
} satisfies Config;

0 commit comments

Comments
 (0)