feat: rewrite sitemap with ISR caching, validation, and filtered allowlist
This commit is contained in:
+14
-44
@@ -1,49 +1,19 @@
|
|||||||
import type { MetadataRoute } from "next"
|
import type { MetadataRoute } from "next"
|
||||||
import { db } from "@/lib/db/index"
|
import { buildStaticEntries } from "@/lib/sitemap/build-static-entries"
|
||||||
import { games, hardware } from "@/lib/db/schema"
|
import { fetchDynamicEntries } from "@/lib/sitemap/fetch-dynamic-entries"
|
||||||
|
|
||||||
const BASE_URL = "https://deckyvault.xyz"
|
/**
|
||||||
|
* ISR revalidation interval for the sitemap.
|
||||||
// Skip static generation — rebuild sitemap at request time with fresh data
|
*
|
||||||
export const dynamic = "force-dynamic"
|
* Instead of `force-dynamic`, we use ISR so the sitemap is cached and
|
||||||
|
* regenerated in the background. This keeps response times fast for
|
||||||
|
* crawlers while still reflecting recent changes on the site.
|
||||||
|
*/
|
||||||
|
export const revalidate = Number(process.env.SITEMAP_REVALIDATE_SECONDS) || 3600
|
||||||
|
|
||||||
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
||||||
// Static pages that don't need DB
|
const staticEntries = buildStaticEntries()
|
||||||
const staticEntries: MetadataRoute.Sitemap = [
|
const { gameEntries, deviceEntries } = await fetchDynamicEntries()
|
||||||
{ url: BASE_URL, lastModified: new Date(), changeFrequency: "weekly" as const, priority: 1 },
|
|
||||||
{ url: `${BASE_URL}/games`, lastModified: new Date(), changeFrequency: "weekly" as const, priority: 0.7 },
|
|
||||||
{ url: `${BASE_URL}/devices`, lastModified: new Date(), changeFrequency: "monthly" as const, priority: 0.6 },
|
|
||||||
{ url: `${BASE_URL}/contact`, lastModified: new Date(), changeFrequency: "monthly" as const, priority: 0.3 },
|
|
||||||
{ url: `${BASE_URL}/login`, lastModified: new Date(), changeFrequency: "monthly" as const, priority: 0.3 },
|
|
||||||
{ url: `${BASE_URL}/signup`, lastModified: new Date(), changeFrequency: "monthly" as const, priority: 0.3 },
|
|
||||||
{ url: `${BASE_URL}/updates`, lastModified: new Date(), changeFrequency: "weekly" as const, priority: 0.5 },
|
|
||||||
]
|
|
||||||
|
|
||||||
try {
|
return [...staticEntries, ...gameEntries, ...deviceEntries]
|
||||||
const [allGames, allDevices] = await Promise.all([
|
}
|
||||||
db.select({ id: games.id, updatedAt: games.updatedAt, capsuleImage: games.capsuleImage }).from(games),
|
|
||||||
db.select({ slug: hardware.slug, createdAt: hardware.createdAt }).from(hardware),
|
|
||||||
])
|
|
||||||
|
|
||||||
const gameEntries: MetadataRoute.Sitemap = allGames.map((game) => ({
|
|
||||||
url: `${BASE_URL}/game/${game.id}`,
|
|
||||||
lastModified: game.updatedAt,
|
|
||||||
changeFrequency: "weekly" as const,
|
|
||||||
priority: 0.8,
|
|
||||||
images: game.capsuleImage ? [game.capsuleImage] : undefined,
|
|
||||||
}))
|
|
||||||
|
|
||||||
const deviceEntries: MetadataRoute.Sitemap = allDevices.map((device) => ({
|
|
||||||
url: `${BASE_URL}/devices/${device.slug}`,
|
|
||||||
lastModified: device.createdAt,
|
|
||||||
changeFrequency: "monthly" as const,
|
|
||||||
priority: 0.6,
|
|
||||||
}))
|
|
||||||
|
|
||||||
return [...staticEntries, ...gameEntries, ...deviceEntries]
|
|
||||||
} catch {
|
|
||||||
// DB unreachable during build — return static sitemap only.
|
|
||||||
// Dynamic entries will be available at request time.
|
|
||||||
return staticEntries
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ async function fetchGameEntries(): Promise<MetadataRoute.Sitemap> {
|
|||||||
return rows.map((row) => {
|
return rows.map((row) => {
|
||||||
const validatedImage = validateImageUrl(row.capsuleImage)
|
const validatedImage = validateImageUrl(row.capsuleImage)
|
||||||
return {
|
return {
|
||||||
url: `${BASE_URL}/games/${row.id}`,
|
url: `${BASE_URL}/game/${row.id}`,
|
||||||
lastModified: row.updatedAt,
|
lastModified: row.updatedAt,
|
||||||
changeFrequency: "weekly" as const,
|
changeFrequency: "weekly" as const,
|
||||||
priority: 0.7,
|
priority: 0.7,
|
||||||
|
|||||||
Reference in New Issue
Block a user