diff --git a/apps/web/app/(site)/notes/[slug]/page.tsx b/apps/web/app/(site)/notes/[slug]/page.tsx new file mode 100644 index 0000000..ea44bb3 --- /dev/null +++ b/apps/web/app/(site)/notes/[slug]/page.tsx @@ -0,0 +1,91 @@ +import type { Metadata } from "next"; +import Link from "next/link"; +import { notFound } from "next/navigation"; +import { Container, Pill } from "@/src/components/site"; +import { NOTES } from "@/src/content/notes"; +import { SITE_NAME, SITE_URL } from "@/src/content/site"; +import { findNoteBySlug } from "@/src/domain/notes"; + +type PageProps = { readonly params: Promise<{ readonly slug: string }> }; + +export const dynamicParams = false; + +export function generateStaticParams() { + return NOTES.map((note) => ({ slug: note.slug })); +} + +export async function generateMetadata({ + params, +}: PageProps): Promise { + const found = findNoteBySlug(NOTES, (await params).slug); + if (!found.ok) return {}; + const { title, summary, slug, publishedOn } = found.value; + const path = `/notes/${slug}`; + return { + title, + description: summary, + alternates: { canonical: path }, + openGraph: { + type: "article", + title, + description: summary, + url: path, + publishedTime: publishedOn, + }, + }; +} + +export default async function Page({ params }: PageProps) { + const found = findNoteBySlug(NOTES, (await params).slug); + if (!found.ok) notFound(); + const { Body, title, summary, slug, publishedOn, readingMinutes, tags } = + found.value; + + const jsonLd = { + "@context": "https://schema.org", + "@type": "Article", + headline: title, + description: summary, + datePublished: publishedOn, + url: `${SITE_URL}/notes/${slug}`, + author: { "@type": "Person", name: SITE_NAME, url: SITE_URL }, + keywords: tags.join(", "), + }; + + return ( + +
+