feat(content): serve the mounted content folder under /content (spec 003)
Audio with range requests, library.json, Homer books; LRC parser. Content stays out of git and the image. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9d063fcbe0
commit
27b1d2fe26
15 files changed
+527
-10
No files matched your search
@@ -11,7 +11,7 @@ shared credits snippet.
|
||||
## Map
|
||||
| Path | Responsibility |
|
||||
|---|---|
|
||||
| `src/server.ts` | `startServer(port)`: routes `/`, `/mockups/NN-slug/` (+ 302 from the no-slash form), 404 otherwise. Runs when `import.meta.main`; `PORT` env, default 3000. |
|
||||
| `src/server.ts` | `startServer(port, { contentDir? })`: routes `/`, `/mockups/NN-slug/` (+ 302 from the no-slash form), `/content/*` via `src/content/routes.ts`, 404 otherwise. Runs when `import.meta.main`; `PORT` env, default 3000. |
|
||||
| `src/index.html`, `src/index.ts`, `src/index.css` | Index page: static cards linking each mockup, then `mountCredits()`. |
|
||||
| `src/mockups/registry.ts` | `mockups: MockupInfo[]` — slug, number, name, pitch, what to try. |
|
||||
| `src/mockups/NN-slug/` | One design direction: `index.html` (links `../../shared/credits.css`, has `<footer data-fan-credits>`), `main.ts`, `style.css`, plus optional helper modules (e.g. `scene.ts`, `layout.ts`). |
|
||||
@@ -22,7 +22,11 @@ shared credits snippet.
|
||||
| `src/shared/audio-slot.ts` | `createAudioSlot(song)`: `<audio>` for `song.audio`, else an empty-state slot. |
|
||||
| `src/shared/video-cards.ts` | `createVideoCards(song)`: YouTube link cards, no embeds. |
|
||||
| `src/shared/credits.css` | Styles for credits, audio slot, video cards. |
|
||||
| `tests/` | `data.test.ts` (dataset invariants), `shared.test.ts` (DOM modules under happy-dom), `server.test.ts` (every route 200s, index links every registry slug, each mockup has the credits hook). |
|
||||
| `src/content/routes.ts` | `contentResponse(req, dir)`: `/content/library.json`, `/content/files/<path>` (traversal-guarded, HTTP ranges), `/content/homer/<odyssey\|iliad>/<book>.json`. All 404 when no folder is mounted. |
|
||||
| `src/content/library.ts` | `scanLibrary(dir)`: sagas (story order) and songs from `Songs and Lyrics/EPIC - <Saga> (<year>)/`; `.lrc` preferred over `.txt`. |
|
||||
| `src/content/homer.ts` | `splitBooks(text)`: Gutenberg Butler text → books (heading, summary, paragraphs). |
|
||||
| `src/shared/lrc.ts` | `parseLrc(text)`: timed lyric lines, sorted. |
|
||||
| `tests/` | `data.test.ts` (dataset invariants), `shared.test.ts` (DOM modules under happy-dom), `server.test.ts` (every route 200s, index links every registry slug, each mockup has the credits hook), `content.test.ts` (LRC, library scan, Homer split, `/content/*` routes on a temp fixture). |
|
||||
| `Dockerfile` | Two-stage `oven/bun:1.3`: install + build, then copy `dist/` and run from `WORKDIR /app/dist`. |
|
||||
|
||||
## Data flow
|
||||
@@ -32,7 +36,9 @@ shared credits snippet.
|
||||
3. `main.ts` renders the direction and calls `mountCredits()` into `<footer data-fan-credits>`.
|
||||
|
||||
## External dependencies
|
||||
None at runtime. Fonts (`@fontsource/*`) and three.js are bundled from npm. Outbound links only: YouTube
|
||||
Optional at runtime: the content folder named by `CONTENT_DIR` (real audio, lyrics, cover art, Butler's
|
||||
Odyssey and Iliad). It is mounted read-only, never committed or baked into the image (spec 003). Without it
|
||||
the site works and `/content/*` answers 404. Otherwise none. Fonts (`@fontsource/*`) and three.js are bundled from npm. Outbound links only: YouTube
|
||||
(video cards) and Project Gutenberg (Odyssey references) — the site works without them.
|
||||
|
||||
## Invariants
|
||||
|
||||
Reference in new issue
Block a user