docs: say that the board has two shapes now

F1 described "one lane per game" as a fact about the timeline, which is
now false half the time, and the prefs key space did not list the pref
that decides it. Both say why the merged board sorts with
endingSoonestFirst rather than a bare end date, since that is the part a
later change is most likely to "simplify".

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Lucas Winther
2026-08-18 22:16:24 +02:00
co-authored by Claude Opus 5
parent 1c8b71e7bf
commit e587e7e106
4 changed files with 24 additions and 5 deletions
+2 -1
View File
@@ -113,9 +113,10 @@ src/client/ React app, service worker, manifest
useCustom.ts — the reader's own games and events (PRD F13)
lens.ts — who sees which rows (focus, outstanding, next-to-expire); pure
zoom.ts — the timeline's scale ladder; pure
lanes.ts — how the timeline stacks: a lane per game, or one deadline queue; pure
scripts/ build-feed.ts, build-static.ts, parse-fixture.ts (offline), refresh-sources.ts (fetches)
serve.ts static server + /api/health
test/ 599 tests
test/ 606 tests
fixtures/<game>/ raw HTML + .expected.json per source — pinned, kept forever
snapshots/ current page per source, rewritten by refresh — see its README
```
+1
View File
@@ -126,6 +126,7 @@ src/
sort.ts deadline order, or what you're partway through
lens.ts who sees which rows — focus, outstanding, next-to-expire
zoom.ts the timeline's scale ladder; pure
lanes.ts how the timeline stacks — lanes, or one deadline queue; pure
useAppUpdate.ts is a newer build waiting, and taking it (F14)
serve.ts static server + /api/health ✓ built
scripts/
+5 -2
View File
@@ -218,12 +218,15 @@ Namespaced, versioned, and small. Nothing here ever goes to the server.
"gacha-tracker:v1:daily" // { [id]: { days: ["2026-08-15", ...], at } }
"gacha-tracker:v1:ignored" // { [eventId]: { at } } — "stop showing me this"
"gacha-tracker:v1:prefs" // { region, hiddenGames[], knownGames[]?, focusGame, sort, view,
// timelineDayWidth, detectDaily, showCompleted, showIgnored,
// regionConfirmed, onboarded }
// timelineDayWidth, timelineGroup, detectDaily, showCompleted,
// showIgnored, regionConfirmed, onboarded }
// timelineDayWidth is px per day on the board, stored as the
// measurement rather than a step number and read through
// snapDayWidth — so a value from an older ladder still opens
// on something renderable.
// timelineGroup is "game" (a lane each) or "ending" (every game
// in one deadline queue). Defaults to "game", so shipping it
// moved nobody's board; see PRD F1.
// knownGames is every lane the reader has been offered. Absent
// means unrecorded, not "offered nothing" — see PRD F8; a lane
// missing from it is new to them and arrives switched off.
+16 -2
View File
@@ -66,8 +66,8 @@ no stored key. A game may have several sources; see `docs/INGESTION.md` § Three
### Features
**F1 — Timeline view.**
A horizontal timeline, one lane per game, spanning a scrollable date range with "today" pinned as a
vertical marker. Each event is a bar from `startsAt` to `endsAt`. Bars are colored by game, and
A horizontal timeline, by default one lane per game, spanning a scrollable date range with "today"
pinned as a vertical marker. Each event is a bar from `startsAt` to `endsAt`. Bars are colored by game, and
completed events render at reduced opacity with a check. Clicking a bar opens a detail panel with
title, type, exact start/end in the user's local timezone, source link, and a completion toggle.
@@ -81,6 +81,20 @@ calendar on screen, and nothing left saying which day, whose game, or which even
six-week bar starts weeks off-screen, so a name that rides off with its own start date leaves a
coloured rectangle behind.
**The reader chooses how it stacks.** Lanes keep a game's events adjacent and comparable, which is
what makes the board readable for someone playing four of them — but that reader also has one queue
of deadlines, and lanes scatter it: what ends tonight sits three lanes below what ends next month,
and no scroll position puts them side by side. So a pair of pills in the board's header switches
between **By game** and **Ending soonest**, and the choice is remembered (`prefs.timelineGroup`,
default `"game"` — the board every existing reader already has). Merged, the order is
`endingSoonestFirst`, the same comparator behind the list's "Ending soonest" (F2), so the two views
cannot mean different things by the same words and an unannounced end still sorts behind every dated
one rather than claiming a place in the queue. Merged there is also no lane heading to say whose
event a bar is, and hue alone cannot answer that once thirteen games share a stack — so each bar
carries its game's short name, with the full name in its tooltip. A bar too narrow for a tag and a
title both keeps the title: a chopped game name reads as a broken word, and the hue and the tooltip
still answer it.
**The reader sets the scale.** A patch cycle is six weeks and a login campaign can run for months,
so no single density answers both "what am I in the middle of this week?" and "how do the next three
months line up?". A pair of controls steps through a ladder of day widths, and the choice is