Files
julian 8223a566e4 docs: import TRM design handoff + defer adoption to phase 3.8
A design handoff bundle generated by Claude Design (claude.ai/design)
on 2026-05-02. Defines the Bloomberg/F1-pit-wall aesthetic for TRM:
- ink-on-paper base + race-flag red accent (#E8412B)
- square-edged everything, sharp printed offset shadows
- mono numerics (JetBrains Mono) for any changing value
- Goldplay (real licensed font, three weights in bundle fonts/)
- four surfaces designed: dashboard / leaderboard / mobile / marketing
  (SPA scope is the first two)

The bundle is committed in-tree at TRM_Design_System-handoff/ so 3.8
has the full source material when it picks the work up. Includes:
- Top-level + project READMEs (the design spec)
- chats/chat1.md (intent + iteration history)
- colors_and_type.css (token set, drop-in for Tailwind 4 @theme)
- fonts/ (Goldplay regular/semibold/bold)
- ui_kits/ (HTML prototypes per surface)
- preview/ (per-token visual reference cards)

Updated phase-3-dogfood-readiness/README.md task 3.8 row to point at
the bundle and document the recommended approach (retheme shadcn via
CSS variable overrides + Tailwind 4 @theme, not replace).

Why deferred: foundational tokens are non-blocking for Phase 1 (login
+ placeholder home) and Phase 2 (live map without chrome). Applying
them now would either delay dogfood-blocking work or land partial
styling that gets reworked when 3.8 lands the full pass.
2026-05-02 19:11:57 +02:00

65 lines
7.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 3 — Dogfood readiness
**Status:** ⬜ Not started
The set of operational features that turn a working pilot into something safe to put in front of race operators on race day. None of these tasks change correctness; they change the experience when things don't go perfectly.
## Outcome statement
When Phase 3 is done:
- **Error boundaries** wrap each major feature region (map, sidebar, header). A crash in the map widget doesn't blank the whole UI; the operator sees a "Map crashed; reload to retry" panel and can keep using the rest.
- **Connection-state UI** is unmissable but not noisy. WS reconnecting → small banner. WS offline > 30s → larger warning. Per-device "last seen N seconds ago" in the device sidebar.
- **Mobile-responsive baseline.** The SPA doesn't crash on a 375px-wide viewport. Map fills the screen; sidebar collapses to a sheet. Not a separate mobile app — the same app, usable in a marshal's pocket browser.
- **Per-device detail panel.** Click a device on the map → side panel showing recent positions, current vehicle/crew, last-seen, manual notes the marshal has typed. Doesn't add data flows; consumes existing snapshots.
- **Operator-friendly empty / loading states.** No blank screens during the snapshot fetch; "No devices reporting yet" message when the event has subscribed but no positions arrived.
- **Vitest + React Testing Library set up.** Unit tests for the auth store, the rAF coalescer, the position-store reducer. Not a comprehensive suite — enough that future changes don't silently regress critical paths.
## Why this is a separate phase
Phase 2 produces a working live map. Phase 3 makes that map _fielded_ — usable when networks are flaky, browsers are exotic, screens are tiny, and operators are stressed. None of these tasks block the map from working in a controlled demo, but all of them affect whether the dogfood is genuinely useful versus a mostly-working tech demo.
## Tasks (sketched, not detailed)
| # | Task | Notes |
| --- | ----------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| 3.1 | Error boundaries + crash-recovery UI | One per major region (map, sidebar, header). Logs to console + optional remote-error endpoint |
| 3.2 | Connection-state UI | Banner / chip in the header; per-device last-seen in the sidebar |
| 3.3 | Mobile-responsive baseline | Tailwind breakpoints; map full-screen on mobile; sidebar → sheet |
| 3.4 | Per-device detail panel | Click → side panel; reads from Directus + position store |
| 3.5 | Empty / loading state polish | "Connecting…", "Waiting for first positions…", "No devices in this event yet" |
| 3.6 | Vitest + React Testing Library setup + targeted tests | Auth store, coalescer, position-store reducer. Not exhaustive |
| 3.7 | Production logging discipline | Console-error captures + optional remote-shipper for stage |
| 3.8 | Visual brand pass — adopt TRM design system | Apply the design handoff bundle. Bundle path + scope + recommended approach below. |
## Acceptance for the phase as a whole
- [ ] All eight tasks (3.13.8) done.
- [ ] Pulling the network mid-session shows a clear "reconnecting" state; reconnecting works; the operator's selection / event-picker state survives the gap.
- [ ] Loading the SPA on an iPhone 12 (or equivalent) viewport doesn't break layout.
- [ ] Clicking a device opens the detail panel; the panel shows the device's current vehicle/crew (joined from Directus) and recent positions (from the store).
- [ ] Vitest runs in CI; existing tests are green; coverage is documented but not gated on a percentage threshold.
- [ ] The dogfood-day operator sign-off: a marshal can use the SPA on race day without us standing over them. (This is the real acceptance gate; the rest is observable proxy.)
## Task 3.8 — TRM design system adoption (deferred from earlier)
A design handoff bundle was generated by Claude Design (claude.ai/design) on 2026-05-02 and lives at `TRM_Design_System-handoff/trm-design-system/` in this repo. It defines a **Bloomberg / F1-pit-wall** aesthetic — high data density, ink-on-paper base with one race-flag red accent (`#E8412B`), mono numerics for any changing value, square-edged everything, sharp printed offset shadows (no blur), Goldplay (real licensed font with three weights in the bundle's `fonts/`) + JetBrains Mono + Inter. Four surfaces designed: web dashboard, live leaderboard, mobile app, marketing site — only the first two are in this SPA's scope.
The bundle's READMEs (top-level + `trm-design-system/README.md` + `project/README.md`) and `chats/chat1.md` are the source of truth. `colors_and_type.css` ships the full token set as CSS custom properties.
**Recommended approach when Phase 3 picks this up — retheme shadcn, don't replace.** Tailwind 4's `@theme` directive maps cleanly to the design's tokens; shadcn's CSS-variable-driven theming lets us keep all the existing primitives (Button / Input / Form / Card / Alert) and only swap the cosmetics. Concrete steps:
1. Translate `colors_and_type.css` into a Tailwind `@theme` block — the paper / ink / night / race-accent / viz palettes all become Tailwind utilities.
2. Override shadcn's `--background`, `--foreground`, `--primary`, `--destructive`, `--ring`, `--radius` to point at the TRM tokens.
3. Add Goldplay as a webfont via the bundle's woff2 / ttf files (drop into `public/fonts/`); register JetBrains Mono via Google Fonts.
4. Set the global radius to `0` (square-edged) and replace shadcn's soft shadows with the printed offset utility (`box-shadow: 2px 2px 0 0 var(--ink)`).
5. Reskin shadcn primitives where defaults conflict — mainly: button radius, card border (full-ink 1 px not hairline), focus ring colour (race-flag red, 2 px outline + offset).
6. Adopt night mode for the Phase 2 live-map page only (the design says night is the default for trackside / kiosk views, not a toggle); paper/ink everywhere else.
7. Replace the home-page placeholder + login page with the design's chrome (56 px top bar, 240/64 px collapsible sidebar — the dashboard layout).
**Out of scope for 3.8:** mobile app and marketing site. Those are separate products in the design system; the SPA only adopts dashboard + leaderboard surfaces.
**Open question for when 3.8 starts:** the design notes the brand may have a custom icon set (cube / pixel-grid / map glyphs from the logo) — Lucide is the documented substitute. Stick with Lucide unless the custom set surfaces by then.
**Why deferred:** the design's foundational tokens are non-blocking for Phase 1 (login + placeholder home) and Phase 2 (live map without chrome). Adopting them now would either delay the dogfood-blocking work or land partial styling that gets reworked in 3.8 anyway. The bundle is committed alongside this plan so it's findable when Phase 3 runs.