feat(mockups): slot 14 voyage with side panel; record verdict on 13
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
e3fd97a78c
commit
3cda08c32e
@@ -1,7 +1,7 @@
|
||||
# EPIC: The Musical Timeline
|
||||
|
||||
Unofficial fan site: an interactive timeline of *EPIC: The Musical* songs. Currently 7 design-direction
|
||||
mockups. Bun 1.3.14 (server, bundler, test runner), TypeScript, three.js (mockups 06/07/13 only), Docker.
|
||||
mockups. Bun 1.3.14 (server, bundler, test runner), TypeScript, three.js (mockups 06/07/13/14 only), Docker.
|
||||
|
||||
`AGENTS.md` is the single source of truth for agents here. `CLAUDE.md` and `GEMINI.md` only point here.
|
||||
Deeper context on demand: `docs/ARCHITECTURE.md`, `docs/DECISIONS.md`, `docs/TODO.md`.
|
||||
@@ -10,7 +10,7 @@ Deeper context on demand: `docs/ARCHITECTURE.md`, `docs/DECISIONS.md`, `docs/TOD
|
||||
|
||||
Install: `bun install --frozen-lockfile`
|
||||
Dev: `bun run dev` (`PORT` env, default 3000)
|
||||
Test: `bun test` | Single file: `bun test tests/data.test.ts` | Single case: `bun test -t "registry has 13"`
|
||||
Test: `bun test` | Single file: `bun test tests/data.test.ts` | Single case: `bun test -t "registry has 14"`
|
||||
Typecheck: `bun run typecheck`
|
||||
Build: `bun run build` | Run the build: `bun run start`
|
||||
Docker: `docker build -t epic-timeline .` then `docker run --rm -p 3000:3000 epic-timeline`
|
||||
|
||||
@@ -53,3 +53,8 @@ artefacts: kept after merge they go stale and contradict the code, so the spec i
|
||||
|
||||
**Decision:** mockup 13 (Curtain call) may use three.js, like 06 and 07. It mocks the frieze → 3D sea →
|
||||
frieze → cave transition, which needs the 3D sea. three.js is already a dependency; nothing new is added.
|
||||
|
||||
## 2026-10-30 — three.js allowed in mockup 14
|
||||
|
||||
**Decision:** mockup 14 (Voyage with side panel) may use three.js; it converges 13's 3D flow with a
|
||||
persistent side panel. No new dependency.
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ or `AGENTS.md` Commands.
|
||||
| `bun install --frozen-lockfile` | worked (no changes) |
|
||||
| `bun test` | worked — 34 pass, 0 fail, 3 files |
|
||||
| `bun test tests/data.test.ts` | worked — 10 pass |
|
||||
| `bun test -t "registry has 13"` | worked — 1 pass |
|
||||
| `bun test -t "registry has 14"` | worked — 1 pass |
|
||||
| `bun run typecheck` | worked (`tsc --noEmit`, exit 0) |
|
||||
| `bun run build` | worked — `dist/server.js` + hashed page assets |
|
||||
| `bun run dev` (`PORT=3113`) | worked — `/` and all mockup routes 200, no-slash form 302 |
|
||||
|
||||
@@ -202,14 +202,36 @@ mockup of the transition.
|
||||
`docs/design/002-sea-chart-spikes/13-curtain-call-report.md`. Preview rebuilt with 01–13.
|
||||
Known rough spots: a small sideways camera shuffle at landfall, sun glare in looks 1/2, a boxy giant.
|
||||
|
||||
### 14. Verdict on 13 Curtain call
|
||||
|
||||
> "Yes it looks pretty good! Small design issues here and there but these can be fixed. 1, 2 and 3 all
|
||||
> look decent. The UI of 2 and 3 tend to look a bit better though. For the models/3d, its better to go
|
||||
> stylistic than realistic. While going through the 3D experience, its still important to have the
|
||||
> right side window open, to show information, paths, lyrics, and fan works."
|
||||
|
||||
- **Accepted:** the curtain-call flow (frieze → sea → landfall → frieze → landing) works; small design
|
||||
issues are fixable later.
|
||||
- **Look:** all three are "decent"; the UI of **2 (two worlds)** and **3 (frieze-led)** looks better.
|
||||
Look 1 (vellum throughout) is effectively out; 2 vs 3 is not decided.
|
||||
- **3D models: stylistic, not realistic.**
|
||||
- **New requirement:** during the 3D experience a **right-side window stays open**, showing:
|
||||
- information (about the current song/place);
|
||||
- paths (motif threads / the route);
|
||||
- lyrics;
|
||||
- fan works.
|
||||
- *(Claude's proposal)* Converge into **14 Voyage with side panel**: 13's flow with stylised models and
|
||||
a persistent right panel (tabs: About · Paths · Lyrics · Fan works), with a 2/3 look toggle.
|
||||
Fan works and lyrics are placeholders (no real lyrics, no real fan artists' names or links).
|
||||
|
||||
## Open questions (in priority order)
|
||||
|
||||
1. ~~Which sea-chart approach (08–11) reads best, or which mix?~~ 11's navigation + 10's style (§9).
|
||||
Then A/B/C inside plates: **A threads** (§12).
|
||||
2. What is the look of the whole: frieze-led (terracotta and black), chart-led (parchment), or
|
||||
something in between? The user is "not sure" yet.
|
||||
3. How do 2D and 3D relate as products? Is the 3D the main experience with the chart inside it, while
|
||||
the chart also stands alone? This is unconfirmed.
|
||||
2. What is the look of the whole? Narrowed to look 2 (two worlds) or 3 (frieze-led) (§14).
|
||||
3. How do 2D and 3D relate as products? Partly answered: in 3D a right-side panel stays open with
|
||||
info, paths, lyrics and fan works (§14). Whether the chart also stands alone is unconfirmed.
|
||||
3b. Fan works: what are they (art, covers, animatics?), where do they come from, and how are they
|
||||
credited? No data model for them yet.
|
||||
4. Which landings are in scope for the first build? The user's examples are the Cyclops' cave, God
|
||||
Games and Ithaca.
|
||||
5. Earlier, still open from 001: lyrics copyright (deferred), branching policy, linter, and what
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
# 14 Voyage with side panel — converge brief
|
||||
|
||||
## Why
|
||||
|
||||
The user's verdict on 13 Curtain call (verbatim):
|
||||
|
||||
> "Yes it looks pretty good! Small design issues here and there but these can be fixed. 1, 2 and 3 all
|
||||
> look decent. The UI of 2 and 3 tend to look a bit better though. For the models/3d, its better to go
|
||||
> stylistic than realistic. While going through the 3D experience, its still important to have the
|
||||
> right side window open, to show information, paths, lyrics, and fan works."
|
||||
|
||||
14 starts from a **copy of 13** (`src/mockups/13-curtain-call/`) and changes three things:
|
||||
|
||||
1. **Persistent right-side panel** (the main new thing).
|
||||
2. **Stylised models**, not realistic.
|
||||
3. **Look toggle 2 / 3 only** (`?look=2|3`, default 2). Drop look 1.
|
||||
|
||||
Keep 13's five beats, transitions, Play/step controls, `?beat=` `?t=` `?play=`, and the small vellum
|
||||
chart. Fix 13's known rough spots while you're there: the sideways camera shuffle at landfall, the big
|
||||
sun glare.
|
||||
|
||||
## 1. The side panel
|
||||
|
||||
- A right-hand panel, about 400–440px wide, **open throughout the 3D beats** (2 sea, 3 landfall,
|
||||
5 cave). The 3D view fills the remaining width; frame the camera so the ship and island sit in the
|
||||
visible area, not behind the panel. During the frieze beats (1, 4) the panel may stay open too
|
||||
(preferred — it should feel like one persistent companion) — your call, but say what you chose.
|
||||
- It can be collapsed to a slim tab, but starts open. `?panel=0` starts collapsed.
|
||||
- It follows the voyage: each beat has a current song (beat 1 The Horse and the Infant, 2 Full Speed
|
||||
Ahead, 3 Polyphemus, 4 Polyphemus, 5 Survive — check ids in `src/data/sample.ts`), and the panel
|
||||
updates with a gentle transition when the beat changes.
|
||||
- Tabs, `?tab=about|paths|lyrics|fan`:
|
||||
- **About** — song title, track number, saga, story time, the Odyssey reference (book/lines from the
|
||||
data), parts with singers, `createAudioSlot` and `createVideoCards` from `src/shared/`.
|
||||
- **Paths** — the route and the motifs: a compact vertical **thread** strip (the user chose threads
|
||||
in 12: soft coloured threads with knots where a motif plays) showing this song's motifs and where
|
||||
each comes from / goes next ("Polyphemus — first heard here · returns in Survive"). Clicking a
|
||||
motif highlights its thread; clicking a song in it is just a highlight (no navigation needed).
|
||||
The small vellum chart may move into this tab or stay on the table — your call.
|
||||
- **Lyrics** — the song's lyrics split by part with singer labels, using the **placeholder** lyrics
|
||||
from the sample data (never real lyrics). Highlight motif lines with the motif colour. A current-part
|
||||
marker is a nice touch, not required.
|
||||
- **Fan works** — 3–4 placeholder cards per song: type (art / animatic / cover / cosplay), a
|
||||
stylised placeholder thumbnail (CSS/SVG, no external images), a made-up clearly-placeholder title,
|
||||
"by @fan-artist" placeholder handle, and a "credit + link to the original" line. Add a visible note
|
||||
"Placeholder fan works — real ones will be credited and linked to their creators." Keep this data
|
||||
local to your folder (e.g. `fanworks.ts`); do not change `src/data/`.
|
||||
- The panel follows the look: look 2 parchment/vellum panel; look 3 dark/terracotta frieze panel.
|
||||
Text must stay comfortably legible (≥15px body, good contrast) in both.
|
||||
|
||||
## 2. Stylised models
|
||||
|
||||
"Stylistic rather than realistic." Make the 3D read like illustration, consistent with the frieze:
|
||||
flat or toon shading (e.g. `MeshToonMaterial` or flat `MeshLambertMaterial` with a stepped gradient
|
||||
map), a limited palette per look, ink outlines (inverted-hull or `EdgesGeometry` lines), simple
|
||||
graphic shapes. Stylised water (flat bands/patterned waves, not a realistic glare). The island a bold
|
||||
graphic shape. **The giant** should become a strong stylised silhouette (black-figure inspired, one
|
||||
eye) rather than boxes. Ship: graphic, silhouette-first.
|
||||
|
||||
## Rules
|
||||
|
||||
- Edit ONLY `src/mockups/14-voyage-panel/` (stub files exist; index.html links credits; main.ts calls
|
||||
`mountCredits()`; replace the stub style.css with unique content). three.js is allowed. Copy from 13
|
||||
(and 04/07/12 if useful) into your folder; don't import across mockup folders.
|
||||
- Credits footer fully visible in every beat and with the panel open.
|
||||
- Build to `/tmp/claude-1000/-home-user-epic-the-musical-timeline/fb650f6d-47a0-47e4-8f6b-197d02417f3b/scratchpad/r3-14`,
|
||||
serve with `cd <outdir> && PORT=4114 bun server.js`. Kill only your own server.
|
||||
- Screenshots 1440×900 with `--use-angle=swiftshader --use-gl=angle --enable-unsafe-swiftshader
|
||||
--virtual-time-budget=6000` (plain `--use-gl=swiftshader` often captures a black stage):
|
||||
`screenshots/14-voyage-panel-beat{1..5}.png` (look 2, tab about),
|
||||
`-paths.png`, `-lyrics.png`, `-fan.png` (beat 3), `-beat2-look3.png`, `-beat5-look3.png`,
|
||||
`-lyrics-look3.png`, `-collapsed.png`. Look at every one; fix what's off.
|
||||
- `bun test` and `bun run typecheck` must pass. Don't commit. Don't spawn subagents.
|
||||
- If you run low on budget, stop and write a pause report (done / checklist / next step) instead.
|
||||
- Report to `docs/design/002-sea-chart-spikes/14-voyage-panel-report.md`: what you built, what works,
|
||||
what doesn't, screenshots, and a short honest comparison of looks 2 and 3 with the panel.
|
||||
@@ -26,6 +26,7 @@
|
||||
<li class="card"><a href="/mockups/11-chart-atlas/"><span class="card__num">11</span><h2>Atlas with insets</h2><p>An overview chart of the whole sea; each saga island opens an inset chart with its songs as ports.</p><p class="card__try">Try this: Open an island's inset, then a song, then zoom back out.</p></a></li>
|
||||
<li class="card"><a href="/mockups/12-vellum-atlas/"><span class="card__num">12</span><h2>Vellum atlas</h2><p>The atlas overview and island plates of 11, drawn in the vellum portolan style of 10.</p><p class="card__try">Try this: Open Cyclops' Island, pick a theme, and switch the plate's motif style (A/B/C).</p></a></li>
|
||||
<li class="card"><a href="/mockups/13-curtain-call/"><span class="card__num">13</span><h2>Curtain call</h2><p>The frieze curtain that carries you from the 2D story into the 3D sea and down into a landing.</p><p class="card__try">Try this: Press Play, or step through: frieze, sea, Cyclops' Island, frieze, cave. Switch the look (1/2/3).</p></a></li>
|
||||
<li class="card"><a href="/mockups/14-voyage-panel/"><span class="card__num">14</span><h2>Voyage with side panel</h2><p>The curtain-call voyage with stylised models and a side panel that stays open: about, paths, lyrics, fan works.</p><p class="card__try">Try this: Play the voyage and watch the panel follow; open Lyrics and Fan works; switch the look (2/3).</p></a></li>
|
||||
</ul>
|
||||
</main>
|
||||
<footer data-fan-credits></footer>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Voyage with side panel — EPIC Timeline mockup</title>
|
||||
<link rel="stylesheet" href="../../shared/credits.css" />
|
||||
<link rel="stylesheet" href="./style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<main id="app"></main>
|
||||
<footer data-fan-credits></footer>
|
||||
<script type="module" src="./main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,3 @@
|
||||
import { mountCredits } from "../../shared/credits";
|
||||
|
||||
mountCredits();
|
||||
@@ -0,0 +1 @@
|
||||
body { margin: 0; --stub-14: 1; }
|
||||
@@ -40,4 +40,7 @@ export const mockups: MockupInfo[] = [
|
||||
{ slug: "13-curtain-call", number: 13, name: "Curtain call",
|
||||
pitch: "The frieze curtain that carries you from the 2D story into the 3D sea and down into a landing.",
|
||||
tryThis: "Press Play, or step through: frieze, sea, Cyclops' Island, frieze, cave. Switch the look (1/2/3)." },
|
||||
{ slug: "14-voyage-panel", number: 14, name: "Voyage with side panel",
|
||||
pitch: "The curtain-call voyage with stylised models and a side panel that stays open: about, paths, lyrics, fan works.",
|
||||
tryThis: "Play the voyage and watch the panel follow; open Lyrics and Fan works; switch the look (2/3)." },
|
||||
];
|
||||
|
||||
@@ -13,6 +13,7 @@ import m9 from "./mockups/10-chart-scroll/index.html";
|
||||
import m10 from "./mockups/11-chart-atlas/index.html";
|
||||
import m11 from "./mockups/12-vellum-atlas/index.html";
|
||||
import m12 from "./mockups/13-curtain-call/index.html";
|
||||
import m13 from "./mockups/14-voyage-panel/index.html";
|
||||
|
||||
export function startServer(port: number): Server<undefined> {
|
||||
return Bun.serve({
|
||||
@@ -45,6 +46,8 @@ export function startServer(port: number): Server<undefined> {
|
||||
"/mockups/12-vellum-atlas": Response.redirect("/mockups/12-vellum-atlas/", 302),
|
||||
"/mockups/13-curtain-call/": m12,
|
||||
"/mockups/13-curtain-call": Response.redirect("/mockups/13-curtain-call/", 302),
|
||||
"/mockups/14-voyage-panel/": m13,
|
||||
"/mockups/14-voyage-panel": Response.redirect("/mockups/14-voyage-panel/", 302),
|
||||
},
|
||||
development: process.env.NODE_ENV !== "production",
|
||||
fetch() {
|
||||
|
||||
@@ -8,7 +8,7 @@ let base: string;
|
||||
beforeAll(() => { server = startServer(0); base = `http://localhost:${server.port}`; });
|
||||
afterAll(() => server.stop(true));
|
||||
|
||||
test("registry has 13 mockups", () => expect(mockups).toHaveLength(13));
|
||||
test("registry has 14 mockups", () => expect(mockups).toHaveLength(14));
|
||||
|
||||
test("index links every mockup", async () => {
|
||||
const res = await fetch(base + "/");
|
||||
|
||||
Reference in New Issue
Block a user