Generative 404: serve a random Hydra work from pln/Hydra
Goal
A generative 404 page on me.nech.pl that renders a random Hydra sketch of mine on every visit — the missing page becomes an art-gallery exit.
Context
- Site: this repo, Next.js 15 App Router, static export (
yarn build→out/), deployed to self-hosted nginx. No server runtime — the 404 page is static HTML (out/404.html). - Hydra works:
content/hydras/*.md(frontmatter:title,source,link) — the sketches live in the public repopln/Hydra(e.g.StarryNights/adenora.js). - The synth embed already exists:
components/hydra-view.js(HydraSynth({ source }), client-only), used by/hydra/[id]viaapp/hydra/[id]/HydraClient.js. - App Router: a root
app/not-found.tsxrenders asout/404.htmlin static export. None exists today — Next emits a default stub.
Enabler first (blocking)
app/hydra/[id]/page.js:21 does a build-time fetch(hydraData.source) — every content/hydras/*.md frontmatter still carries source: URLs at git.plnech.fr (dead host, post-migration). Rewrite them mechanically to the migrated raw path:
- from
https://git.plnech.fr/pln/Hydra/raw/master/<path> - to
https://git.nech.pl/pln/Hydra/-/raw/master/<path>
One commit, scriptable, no content changes beyond URLs. Verify: rg -c 'git.plnech.fr' content/hydras/ → 0, and yarn build fetches succeed (no /hydra build errors).
Design (the ticket proper)
-
app/not-found.tsx(server component): read all hydras viagetHydrasData()(lib/hydras.js), fetch each sketch's code at build (same pattern as/hydra/[id]), pass the full list to a client leaf. Random-per-request is impossible server-side in static export — randomness lives client-side. - Client leaf (
'use client'): pick uniformly at random on mount (useEffect — avoid hydration mismatch, render nothing until picked), render<HydraSynth source={code} />full-viewport behind the 404 text. Exclude from the pick any sketch whose code fetch failed or came back empty — one broken URL must not blank the page. - UI text: factual, minimal. Title
404, one line linking home (/) and the drawn work's page (/hydra/<slug>). No marketing copy. - Reuse
next/dynamic({ ssr: false })inside a'use client'leaf (the ssr:false option is only valid in client components — same pattern asapp/hydra/[id]/HydraClient.js). - Bundle sanity: ~30 sketch code strings as props is fine (few KB each); no dynamic import of code, no eval beyond what HydraSynth already does.
Deploy note (owner applies — SRE repo)
The erable vhost needs error_page 404 /404.html; in the :443 block — file SRE/nechpl-www/me/deploy/nginx/me.nech.pl.conf. Propose the exact diff as a comment on this issue; do NOT commit to SRE (your deploy key is scoped to this repo only).
Rules
- Feature branch
feat/generative-404—mainis protected, you cannot push it (by design). -
yarn buildexit 0;out/404.htmlcontains the client leaf + text;/hydrapages regenerate. - Commits: conventional style, no AI fingerprints, no people names.
- Content rule: no generated prose beyond the factual UI text; the sketches are code — wiring them is your job, not writing them.
- Push the branch, open an MR. Review is mine.
Test
Serve out/ locally (python3 -m http.server -d out 8123), curl /nonexistent → 404.html with the leaf markup; confirm the pick pool includes every valid hydra slug.