Repository Public
1import type { MetadataRoute } from "next";2import { sql } from "@/lib/db";34export const dynamic = "force-dynamic";5const BASE = process.env.PUBLIC_URL ?? "https://clip.spboucher.ai";6export default async function sitemap(): Promise<MetadataRoute.Sitemap> {7 const films = await sql<{ slug: string; published_at: Date; master_sha: string; title_en: string; synopsis_en: string; poster_sha: string; duration: number }[]>`8 SELECT slug, published_at, master_sha, title_en, synopsis_en, poster_sha, duration FROM films WHERE status = 'published' ORDER BY published_at DESC`;9 const series = await sql<{ slug: string }[]>`SELECT slug FROM series ORDER BY sort`;10 const both = (path: string, extra: Partial<MetadataRoute.Sitemap[number]> = {}): MetadataRoute.Sitemap[number] => ({11 url: `${BASE}${path}`, alternates: { languages: { en: `${BASE}${path}`, fr: `${BASE}/fr${path === "/" ? "" : path}` } }, ...extra,12 });13 return [14 both("/", { changeFrequency: "daily", priority: 1 }), both("/feed", { changeFrequency: "daily" }), both("/explore"), both("/series"), both("/about"),15 ...series.map((s) => both(`/series/${s.slug}`)),16 ...films.map((f) => both(`/film/${f.slug}`, {17 lastModified: f.published_at,18 videos: [{ title: f.title_en, description: f.synopsis_en, thumbnail_loc: `${BASE}/media/${f.poster_sha}.jpg`, content_loc: `${BASE}/media/${f.master_sha}.mp4`, duration: Math.round(Number(f.duration)) }],19 })),20 ];21}22