Add .planning/ scaffolding: - ROADMAP.md (4 phases, 8 non-negotiable design rules) - phase-1-foundation/ README + 9 task files (1.2-1.10) - phase-2-live-map / phase-3-dogfood-readiness / phase-4-future README placeholders Task 1.2 — stack rounding-out: - Tailwind 4 via @tailwindcss/vite + src/styles/globals.css - shadcn/ui (slate, new-york) primitives in src/ui/primitives/: button, input, label, form, card, alert - TanStack Router 1.169 + Query 5.100 (devtools + plugin in devDeps) - Zustand 5, @directus/sdk 21, zod 4, react-hook-form 7 + resolvers - Prettier 3 + eslint-config-prettier + eslint-plugin-prettier - ESLint override disabling react-refresh/only-export-components for src/ui/primitives/** (intentional dual-exports in shadcn primitives) - Path alias @/* -> ./src/* in tsconfig.json + tsconfig.app.json (TS 6 deprecates baseUrl; paths now resolve relative to config file). Pulled forward from 1.3 because shadcn add CLI needs it resolvable. - Scripts: dev, build, preview, lint, typecheck, format, format:check, test (placeholder) - App.tsx Tailwind smoke test (centred card + shadcn Button) - README.md rewritten with stack/scripts/shadcn-add docs All four gates green: typecheck, lint, format:check, build (222KB / 70KB gz).
3.1 KiB
Phase 4 — Future / optional
Status: ❄️ Not committed
Ideas on radar that may or may not become real tasks. Captured here so they don't get forgotten and so we have a place to push scope creep that surfaces during Phases 1–3.
None of these are committed. Move them out of Phase 4 and into a numbered phase only when there's a concrete reason to do them.
Candidates
-
Geometry editor. Full CRUD on
geofences/waypoints/speed_limit_zonesvia@mapbox/mapbox-gl-draw. Drawing tools, vertex snapping, polygon validation, import from roadbook coordinates. Depends on directus Phase 2 — those collections don't exist yet. When directus Phase 2 lands, promote this to its own SPA phase. -
Replay mode. Read historical positions for an event + time range, animate them on the map at chosen playback speed. Useful for: post-race review, debugging "where did we lose position from this device", validating a new geofence against past races. Needs a Processor-side replay endpoint (mentioned in
trm/processor/.planning/phase-4-future/README.mdas "replay tooling"). -
Heatmaps / density visualisation via deck.gl. Layer on top of MapLibre showing position density over time. For a 24-hour rally with 500 racers, the line density on a single stage is a useful at-a-glance "where did people struggle / where was traffic" view. deck.gl integrates as a layer on top of the existing map; no architectural rework.
-
i18n (Albanian). The dogfood is closed and the operators speak English. Public-facing pages (eventually, when they exist) need Albanian.
react-i18nextis the boring answer; defer until there's a public surface. -
Dark mode. shadcn/ui supports it natively via Tailwind class strategy. Trivial to add when someone wants it; not worth doing speculatively.
-
End-to-end tests with Playwright. Login → subscribe → see positions → log out, run against a stack with mocked Processor positions. Worth doing when (a) Phase 1 is stable and (b) regressions have started costing real time. Until then, manual smoke + Vitest + the dogfood itself are sufficient.
-
Per-event leaderboard / standings page. Read derived results from processor's Phase 2 timing tables (
stage_results). Out of dogfood scope (manual results), but a real product feature for "after dogfood succeeds and we want to add real value." -
Spectator-facing public live map. Same map widget, no auth, scoped to one public event. Different deployment shape (CDN-friendly, no cookies, possibly a separate origin). Requires directus Phase 4 (permissions) to be landed first so authorization makes sense.
-
Notifications. Browser push for "device went silent" or "speed-limit zone violation" alerts. Requires service worker + the Notifications API + a way for processor to push notification triggers. Material work; high operator value if we get there.
-
Operator chat / coordination. Race directors and marshals talking to each other inside the SPA during the event. Out of architectural scope (TRM is a tracking platform, not a comms platform), but easy to imagine an embedded Matrix or similar widget. Park here until someone makes the case.