From 4eb663f42a71d1d9408947509ae741dbea502e69 Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Sat, 3 Oct 2026 19:21:00 +0200 Subject: [PATCH] feat: add /notes with two engineering write-ups and diagrams Co-Authored-By: Claude Sonnet 5.5 --- apps/web/app/(site)/notes/[slug]/page.tsx | 91 +++++++++ apps/web/app/(site)/notes/page.tsx | 41 +++- .../src/components/notes/CoreShellDiagram.tsx | 151 ++++++++++++++ .../components/notes/GatePipelineDiagram.tsx | 115 +++++++++++ apps/web/src/components/notes/NoteProse.tsx | 39 ++++ .../functional-core-imperative-shell.tsx | 121 +++++++++++ apps/web/src/content/notes/index.ts | 16 ++ .../src/content/notes/spec-first-gates.tsx | 142 +++++++++++++ apps/web/src/content/notes/types.ts | 4 + apps/web/src/domain/notes.spec.ts | 193 ++++++++++++++++++ apps/web/src/domain/notes.ts | 83 ++++++++ 11 files changed, 992 insertions(+), 4 deletions(-) create mode 100644 apps/web/app/(site)/notes/[slug]/page.tsx create mode 100644 apps/web/src/components/notes/CoreShellDiagram.tsx create mode 100644 apps/web/src/components/notes/GatePipelineDiagram.tsx create mode 100644 apps/web/src/components/notes/NoteProse.tsx create mode 100644 apps/web/src/content/notes/functional-core-imperative-shell.tsx create mode 100644 apps/web/src/content/notes/index.ts create mode 100644 apps/web/src/content/notes/spec-first-gates.tsx create mode 100644 apps/web/src/content/notes/types.ts create mode 100644 apps/web/src/domain/notes.spec.ts create mode 100644 apps/web/src/domain/notes.ts 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 ( + +
+