Add auto-updating sitemap.xml and robots.txt

Sitemap combines hardcoded static routes with Payload's Pages and
published Posts collections (hourly ISR revalidation), so new CMS
pages/blog posts appear without a code change. Excludes noindex
transactional routes (checkout, cart, bestellbestaetigung,
newsletter-confirmed, konto/*) to avoid Search Console warnings.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Eg6h91yngXmSnM51wxXM8
This commit is contained in:
Marco
2026-08-29 21:28:42 +00:00
parent 33f3adb92c
commit 06fee1739d
3 changed files with 121 additions and 0 deletions
+43
View File
@@ -1518,3 +1518,46 @@ export async function getPageBySlug(slug: string, options?: { draft?: boolean })
if (!doc) return null;
return mapPayloadPage(doc);
}
export type SitemapEntry = { slug: string; updatedAt: string };
// Backs app/sitemap.ts. Pages has no status/draft field (see Pages.ts) —
// every doc that exists is live — so unlike getBlogPosts there's no
// `where[status]` filter needed here.
export async function getAllPageSlugs(): Promise<SitemapEntry[]> {
const params = new URLSearchParams({
"where[tenant.slug][equals]": TENANT_SLUG,
depth: "0",
limit: "100",
});
const res = await fetch(`${PAYLOAD_URL}/api/pages?${params}`, { next: { revalidate: 3600 } });
if (!res.ok) {
console.error(`getAllPageSlugs: Payload returned ${res.status} ${res.statusText}`);
return [];
}
const data: { docs?: { slug: string; updatedAt: string }[] } = await res.json();
return (data.docs ?? []).map((doc) => ({ slug: doc.slug, updatedAt: doc.updatedAt }));
}
// Same shape as getAllPageSlugs but for Posts, which — unlike Pages — does
// have a draft/scheduled state, so this filters to `published` the same
// way getBlogPosts does (the sitemap must never list a post that 404s).
export async function getAllPostSlugs(): Promise<SitemapEntry[]> {
const params = new URLSearchParams({
"where[tenant.slug][equals]": TENANT_SLUG,
"where[status][equals]": "published",
depth: "0",
limit: "100",
});
const res = await fetch(`${PAYLOAD_URL}/api/posts?${params}`, { next: { revalidate: 3600 } });
if (!res.ok) {
console.error(`getAllPostSlugs: Payload returned ${res.status} ${res.statusText}`);
return [];
}
const data: { docs?: { slug: string; updatedAt: string }[] } = await res.json();
return (data.docs ?? []).map((doc) => ({ slug: doc.slug, updatedAt: doc.updatedAt }));
}