import { Metadata } from "next"; import { notFound, redirect } from "next/navigation"; import { cache } from "react"; import { defineQuery } from "next-sanity"; import { sanity } from "@/lib/sanity"; import { AnimatedText } from "@/components/AnimatedText"; import { ReleaseCover } from "@/components/release/ReleaseCover"; import { StreamingLinks } from "@/components/release/StreamingLinks"; import { urlFor } from "@/lib/sanityImage"; import { ARTIST_PLACEHOLDER_SRC } from "@/lib/constants"; import { buildLinks, type Release } from "@/lib/release"; export const dynamicParams = true; export const revalidate = 86400; const RELEASE_BY_CATALOG_NO_QUERY = defineQuery(` *[_type == "release" && lower(catalogNo) == $slug][0]{ name, albumArtist, label, catalogNo, albumCover, officialUrl, spotifyUrl, appleMusicUrl, deezerUrl, amazonMusicUrl, tidalUrl, qobuzUrl, } `); const getRelease = cache(async (slug: string) => { try { const release = await sanity.fetch(RELEASE_BY_CATALOG_NO_QUERY, { slug }); return release; } catch (error) { console.error("Failed to fetch release:", error); return null; } }); const RELEASE_CATALOG_SLUGS_QUERY = defineQuery( `*[_type == "release" && defined(catalogNo)][]{ "slug": lower(catalogNo) }`, ); export async function generateStaticParams() { const releases = await sanity.fetch<{ slug: string }[]>(RELEASE_CATALOG_SLUGS_QUERY); return releases.map(({ slug }) => ({ slug })); } export async function generateMetadata({ params, }: { params: Promise<{ slug: string }>; }): Promise { const { slug } = await params; if (!slug) return { title: "TRPTK" }; const release = await getRelease(slug.toLowerCase()); if (!release) return { title: "TRPTK" }; const description = `Listen to ${release.name}${release.albumArtist ? ` by ${release.albumArtist}` : ""} on all major streaming platforms.`; const ogImage = release.albumCover ? urlFor(release.albumCover).width(1200).height(1200).url() : undefined; return { title: `${release.albumArtist ? `${release.albumArtist} • ` : ""}${release.name}`, description, openGraph: { title: release.name, description: `${release.albumArtist || "TRPTK"}${release.label ? ` - ${release.label}` : ""}`, type: "music.album", ...(ogImage && { images: [{ url: ogImage, width: 1200, height: 1200, alt: `${release.name} by ${release.albumArtist}` }] }), }, twitter: { card: "summary_large_image", title: release.name, description, ...(ogImage && { images: [ogImage] }), }, }; } export default async function ReleasePage({ params }: { params: Promise<{ slug: string }> }) { const { slug } = await params; if (!slug) notFound(); const normalizedSlug = slug.toLowerCase(); if (slug !== normalizedSlug) { redirect(`/${normalizedSlug}`); } const release = await getRelease(slug); if (!release) notFound(); const links = buildLinks(release); const title = release.name ?? slug; const albumArtist = release.albumArtist ?? ""; return (
); }