feat(content): prefer Greek-name Homer translations; voyage app spec, design record and plan

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-10-30 04:50:11 +01:00
1 parent 9a0350c82f
commit c11c2ef079
9 files changed
+372 -8

No files matched your search

+71
View File
@@ -0,0 +1,71 @@
---
status: approved
---
# 002 — The voyage app (v1)
Status: approved by user 2026-10-30 (direction approval; the user's standing rule: carry an approved
design through spec → plan → execution without review stops). Design record:
`docs/design/002-voyage-app.md`. Content source: `docs/specs/003-content-mount.md`.
## Intent
Turn the approved mockup direction (17) into the real site at `/`: the whole album (9 sagas, 40 songs)
as a stylised 3D sea voyage with the frieze as the curtain call between scenes, three landing
sublevels, a persistent side panel, and a bottom timeline of motif threads, using the real audio,
synced lyrics and the Odyssey text from the mounted content folder.
## Goals
1. **Routes.** The app is served at `/`. The mockup gallery moves to `/mockups/` (mockups stay at
`/mockups/NN-slug/`). Every page keeps the fan notice and credit.
2. **Data for the whole album.** `src/data/` describes 9 sagas and 40 songs in album order (titles and
track numbers as in the content folder) with: story time (years after Troy + a label), the Odyssey
reference as a **book number and passage keywords** (Butler's prose has no line numbers), singers,
motifs per song (and per part where known), facts, and video links. A curated motif set (musical
motifs and character themes) with stable colours. Anything not certain is marked `// TODO(verify)`.
Fan works: a typed, credited list (title, creator, type, URL, licence/permission note), **empty in
v1** — no invented works.
3. **The voyage.** One 3D world: a route past nine places (Troy, the Cyclops' island, the open sea/storm,
Aeaea, the Underworld, Scylla/the thunder sea, Olympus/the wisdom sea, Charybdis/vengeance, Ithaca).
Each song is a stop on the route; selecting a song sails the ship there. Stylised per the design
record.
4. **Curtain call.** Entering a saga (from the previous saga or by jumping) drops that saga's frieze
band (black-figure on terracotta, the saga's name and its song titles as inscriptions), which then
lifts into the sea with the horizon on the frieze's ground line. Within a saga, songs change without
the curtain. Jumps across several sagas fade through the curtain colour.
5. **Three landings.** Cyclops' cave, the God Games arena (Athena), Ithaca's hall. Each is entered from
its saga's frieze ("Go ashore") or automatically when its song is chosen (Survive; God Games; the
Ithaca songs from The Challenge on — exact song→landing mapping in the plan), and left with
"Back to sea".
6. **Side panel** with About, Listen & lyrics (player + synced lyrics + Watch), Paths (motif detail +
strip when the timeline is hidden + chart of the nine places), Fan works (list or empty state).
Collapsible; header play button.
7. **Bottom timeline** for 40 songs: all sagas visible as groups; the current saga expanded with
titles, other sagas compact; you-are-here; motif threads for the current song's motifs across the
whole album. Hideable (strip moves into Paths). "Threads on the sea" toggle.
8. **Navigation and state.** Previous/next song (buttons, ←/→), click any stop, Play voyage (steps
through songs, silent), deep links (`?song=`, `?tab=`, `?motif=`, `?timeline=`, `?ribbons=`), browser
back/forward restore state. Esc closes the reading view / leaves a landing.
9. **Robustness.** Works without the content folder (no audio/lyrics, a clear note). Works without
WebGL (the frieze and panel still navigate; a note explains). Respects `prefers-reduced-motion`
(crossfades). Keyboard reachable with visible focus. Desktop first (1280–1920 wide); below 900px
the panel becomes a bottom sheet and the timeline compact — usable, not polished.
## Non-goals (v1)
- Bespoke frieze art for every song; per-saga friezes may reuse a shared figure kit.
- Time-aligning parts and motifs to the recordings (needs a content mapping file; see 17's report).
- Collecting real fan works; mobile polish; i18n; removing the mockups.
## Acceptance criteria
- `bun test` covers: the dataset (40 songs matching the content folder's titles and order, every motif
used and defined, story times non-decreasing in album order, every song in exactly one saga),
the route/stop geometry (one stop per song, ordered along the route), URL state round-trip, timeline
layout (40 stops, no title overlaps in the expanded saga), and the `/` and `/mockups/` routes.
- With the content folder mounted, at 1440×900: every saga's frieze, each landing, the panel tabs,
playback with synced lyrics, and the timeline/ribbons render correctly in headless screenshots that
were looked at; without it, the fallback renders.
- `bun run typecheck`, `bun run build` pass; the preview container serves the app at `/`.
- Docs: ARCHITECTURE, DECISIONS, DESIGN.md (the chosen direction as tokens and rules), AGENTS.md, TODO.
+3 -2
View File
@@ -25,8 +25,9 @@ it from a path given by `CONTENT_DIR`, mounted read-only into the container.
audio URL, lyrics URL and whether they are timed), built by scanning the folder.
- `GET /content/files/<path>` — the file at that path inside `CONTENT_DIR`, with the right content
type and HTTP range support so audio can seek. Paths outside `CONTENT_DIR` are refused.
- `GET /content/homer/<odyssey|iliad>/<book>.json` — one book of the Butler text: number, heading,
summary line, paragraphs.
- `GET /content/homer/<odyssey|iliad>/<book>.json` — one book: number, heading, summary line,
paragraphs. Prefers the Greek-names translations (Butcher & Lang's Odyssey, #1728; Lang, Leaf &
Myers' Iliad, #3059) when present in the folder, else Butler's (#1727, #2199).
- Without `CONTENT_DIR` (or with a missing folder), all `/content/*` routes answer 404 and every
other route works as before.
2. **Shared helpers** for clients: an LRC parser (timed lines, sorted, multi-stamp lines, metadata tags