roadmap.org
1 #+title: Mission Control Dashboard - Implementation Roadmap 2 #+author: PRD Generator 3 #+date: [2026-04-02 Thu] 4 #+startup: indent 5 #+options: toc:t num:t 6 7 * Roadmap Overview 8 9 This file breaks down the PRD into independently-grabbable Radicle issues 10 using tracer-bullet vertical slices. 11 12 ** Tracer Bullet Strategy 13 14 Each issue is designed to: 15 - Be independently implementable in 20-60 minutes 16 - Produce visible progress on the map 17 - Work end-to-end (even if minimal) 18 - Stand on its own as a commit 19 20 ** Issue Categories 21 22 | Category | Description | Issues | 23 |----------+-------------------------------------------+--------| 24 | Setup | Project scaffolding, dependencies, config | 1-4 | 25 | Phase 1 | Aircraft polling with OpenSky | 5-11 | 26 | Phase 2 | Mission assets over WebSocket | 12-18 | 27 | Phase 3 | Transit vehicles via SSE | 19-24 | 28 | Polish | Integration, UI refinement, docs | 25-27 | 29 | Future | Stretch goals | 28-32 | 30 31 * Setup Issues 32 33 ** Issue 001: Scaffold TanStack Start Project [#DONE] 34 :PROPERTIES: 35 :RADICLE-KEY: MC-001 36 :TRACER-BULLET: yes 37 :END: 38 39 - [X] Project created with `npx @tanstack/cli@latest create mission-control` 40 - [X] Dev server runs and shows default starter page 41 - [X] TypeScript configured with strict mode 42 - [X] Routing structure works (`/` route renders) 43 - [X] No type errors in editor 44 - [X] Closed: Radicle issue 9bc5329 (and duplicate 1e87efc) 45 46 ** Issue 002: Install Dependencies 47 :PROPERTIES: 48 :RADICLE-KEY: MC-002 49 :TRACER-BULLET: yes 50 :END: 51 52 - [X] Install leaflet + react-leaflet 53 - [X] Install xstate + @xstate/react (connection lifecycle machines) 54 - [X] Install @xstate/store (shared application state — see [[file:../doc/decisions/adr_001_state_store_selection.org][ADR-001]]) 55 - [X] Install @types/leaflet (dev) 56 - [X] Verify no type errors 57 - [X] Commit: "feat: install mapping and state libraries" 58 59 ** Issue 003: Configure Project Structure 60 :PROPERTIES: 61 :RADICLE-KEY: MC-003 62 :TRACER-BULLET: yes 63 :END: 64 65 - [X] Create src/types/ directory 66 - [X] Create src/components/ directory 67 - [X] Create src/machines/ directory (XState connection lifecycle) 68 - [X] Create src/stores/ directory (@xstate/store shared state) 69 - [X] Create src/server/ directory (TanStack server functions) 70 - [X] Configure tsconfig paths (optional) 71 - [X] Commit: "chore: set up project structure" 72 73 See [[file:../doc/decisions/adr_001_state_store_selection.org][ADR-001]] for state management architecture. 74 75 ** Issue 004: Set Up Root Layout 76 :PROPERTIES: 77 :RADICLE-KEY: MC-004 78 :TRACER-BULLET: yes 79 :END: 80 81 - [X] Update __root.tsx with proper head meta 82 - [X] Add Leaflet CSS to document head 83 - [X] Configure document structure 84 - [X] Verify app renders correctly 85 - [X] Commit: "feat: set up root layout" 86 87 * Phase 1: Aircraft Polling 88 89 ** Issue 005: Define Aircraft Type 90 :PROPERTIES: 91 :RADICLE-KEY: MC-005 92 :TRACER-BULLET: yes 93 :END: 94 95 - [ ] Create src/types/aircraft.ts 96 - [ ] Define Aircraft interface with all fields 97 - [ ] Mark nullable fields appropriately 98 - [ ] Export types for use across project 99 - [ ] Commit: "feat: define aircraft type" 100 101 ** Issue 006: Create Server Function for OpenSky 102 :PROPERTIES: 103 :RADICLE-KEY: MC-006 104 :TRACER-BULLET: yes 105 :END: 106 107 - [ ] Create src/server/opensky.ts 108 - [ ] Define bounding box for Switzerland 109 - [ ] Implement parseStateVector() 110 - [ ] Handle null/undefined fields 111 - [ ] Commit: "feat: create OpenSky server function" 112 113 ** Issue 007: Build Aircraft Polling Machine 114 :PROPERTIES: 115 :RADICLE-KEY: MC-007 116 :TRACER-BULLET: yes 117 :END: 118 119 - [ ] Create src/machines/aircraftPollingMachine.ts 120 - [ ] Define context (aircraft, error, lastUpdated) 121 - [ ] Implement fetching/wainting states 122 - [ ] Add 10s after delay 123 - [ ] Commit: "feat: create aircraft polling XState machine" 124 125 ** Issue 008: Create Aircraft Marker Component 126 :PROPERTIES: 127 :RADICLE-KEY: MC-008 128 :TRACER-BULLET: yes 129 :END: 130 131 - [ ] Create src/components/AircraftMarker.tsx 132 - [ ] Implement aircraft icon with L.divIcon 133 - [ ] Add popup with telemetry 134 - [ ] Handle null latitude/longitude 135 - [ ] Add click handler for selection 136 - [ ] Commit: "feat: create aircraft marker component" 137 138 ** Issue 009: Create Aircraft CSS 139 :PROPERTIES: 140 :RADICLE-KEY: MC-009 141 :TRACER-BULLET: yes 142 :END: 143 144 - [ ] Create src/aircraft.css 145 - [ ] Style aircraft icon 146 - [ ] Ensure clean rendering 147 - [ ] Commit: "feat: add aircraft marker styles" 148 149 ** Issue 010: Integrate Polling Machine into Map 150 :PROPERTIES: 151 :RADICLE-KEY: MC-010 152 :TRACER-BULLET: yes 153 :END: 154 155 - [ ] Update src/components/Map.tsx 156 - [ ] Wire up useMachine hook 157 - [ ] Render AircraftMarker components 158 - [ ] Implement telemetry sidebar 159 - [ ] Commit: "feat: integrate aircraft polling into map" 160 161 ** Issue 011: Add Polling State Display 162 :PROPERTIES: 163 :RADICLE-KEY: MC-011 164 :TRACER-BULLET: yes 165 :END: 166 167 - [ ] Show polling state (fetching/waiting) in sidebar 168 - [ ] Display last update time 169 - [ ] Show aircraft count 170 - [ ] Handle and display errors 171 - [ ] Commit: "feat: display polling state in sidebar" 172 173 * Phase 2: WebSocket Mission Assets 174 175 ** Issue 012: Define Mission Types 176 :PROPERTIES: 177 :RADICLE-KEY: MC-012 178 :TRACER-BULLET: yes 179 :END: 180 181 - [ ] Create src/types/mission.ts 182 - [ ] Define MissionAsset interface 183 - [ ] Define MissionAlert interface 184 - [ ] Define MissionMessage type 185 - [ ] Commit: "feat: define mission types" 186 187 ** Issue 013: Build Mission WebSocket Machine 188 :PROPERTIES: 189 :RADICLE-KEY: MC-013 190 :TRACER-BULLET: yes 191 :END: 192 193 - [ ] Create src/machines/missionWebSocketMachine.ts 194 - [ ] Define context (assets, alerts, connected) 195 - [ ] Implement connecting/reconnecting/streaming states 196 - [ ] Add fromCallback WebSocket actor 197 - [ ] Commit: "feat: create WebSocket XState machine" 198 199 ** Issue 014: Create Mission Marker Component 200 :PROPERTIES: 201 :RADICLE-KEY: MC-014 202 :TRACER-BULLET: yes 203 :END: 204 205 - [ ] Create src/components/MissionMarker.tsx 206 - [ ] Implement three icons (drone/vehicle/sensor) 207 - [ ] Add popup with status/battery 208 - [ ] Commit: "feat: create mission marker component" 209 210 ** Issue 015: Create Alerts Sidebar Component 211 :PROPERTIES: 212 :RADICLE-KEY: MC-015 213 :TRACER-BULLET: yes 214 :END: 215 216 - [ ] Create src/components/AlertsSidebar.tsx 217 - [ ] Implement severity-based styling 218 - [ ] Show no alerts state 219 - [ ] Commit: "feat: create alerts sidebar" 220 221 ** Issue 016: Update Map to Include Mission Assets 222 :PROPERTIES: 223 :RADICLE-KEY: MC-016 224 :TRACER-BULLET: yes 225 :END: 226 227 - [ ] Import missionWebSocketMachine 228 - [ ] Render MissionMarker components 229 - [ ] Wire up AlertsSidebar 230 - [ ] Commit: "feat: add mission assets to map" 231 232 ** Issue 017: Create WebSocket Server (VPS) 233 :PROPERTIES: 234 :RADICLE-KEY: MC-017 235 :TRACER-BULLET: yes 236 :END: 237 238 - [ ] Set up project on VPS 239 - [ ] Initialize Node.js project 240 - [ ] Install ws package 241 - [ ] Create server.js with asset simulation 242 - [ ] Start and verify server 243 - [ ] Commit: "feat: create WebSocket server for mission assets" 244 245 ** Issue 018: Test WebSocket Connection 246 :PROPERTIES: 247 :RADICLE-KEY: MC-018 248 :TRACER-BULLET: yes 249 :END: 250 251 - [ ] Configure VPS IP in machine 252 - [ ] Verify connection in browser 253 - [ ] Test reconnection after disconnect 254 - [ ] Commit: "test: verify WebSocket reconnection" 255 256 * Phase 3: SSE Transit Vehicles 257 258 ** Issue 019: Define Transit Types 259 :PROPERTIES: 260 :RADICLE-KEY: MC-019 261 :TRACER-BULLET: yes 262 :END: 263 264 - [ ] Create src/types/transit.ts 265 - [ ] Define TransitVehicle interface 266 - [ ] Export for use across project 267 - [ ] Commit: "feat: define transit types" 268 269 ** Issue 020: Build Transit SSE Machine 270 :PROPERTIES: 271 :RADICLE-KEY: MC-020 272 :TRACER-BULLET: yes 273 :END: 274 275 - [ ] Create src/machines/transitSSEMachine.ts 276 - [ ] Define SSEEvent union type 277 - [ ] Implement streaming state 278 - [ ] Add handlers for reset/update/add/remove 279 - [ ] No reconnection state needed 280 - [ ] Commit: "feat: create SSE XState machine" 281 282 ** Issue 021: Create Transit Marker Component 283 :PROPERTIES: 284 :RADICLE-KEY: MC-021 285 :TRACER-BULLET: yes 286 :END: 287 288 - [ ] Create src/components/TransitMarker.tsx 289 - [ ] Implement bus icon 290 - [ ] Add popup with route/status 291 - [ ] Commit: "feat: create transit marker component" 292 293 ** Issue 022: Add Transit Machine to Map 294 :PROPERTIES: 295 :RADICLE-KEY: MC-022 296 :TRACER-BULLET: yes 297 :END: 298 299 - [ ] Import transitSSEMachine 300 - [ ] Render TransitMarker components 301 - [ ] Verify SSE connection 302 - [ ] Commit: "feat: add transit vehicles to map" 303 304 ** Issue 023: Test MBTA API Connection 305 :PROPERTIES: 306 :RADICLE-KEY: MC-023 307 :TRACER-BULLET: yes 308 :END: 309 310 - [ ] Get MBTA API key 311 - [ ] Configure key in machine 312 - [ ] Verify vehicles appear 313 - [ ] Test auto-reconnection 314 - [ ] Commit: "test: verify MBTA SSE connection" 315 316 ** Issue 024: Handle SSE Event Types 317 :PROPERTIES: 318 :RADICLE-KEY: MC-024 319 :TRACER-BULLET: yes 320 :END: 321 322 - [ ] Verify reset event clears all vehicles 323 - [ ] Verify update modifies existing vehicle 324 - [ ] Verify add appends new vehicle 325 - [ ] Verify remove filters vehicle 326 - [ ] Commit: "feat: handle all SSE event types" 327 328 * Integration & Polish 329 330 ** Issue 025: Combine All Three Data Sources 331 :PROPERTIES: 332 :RADICLE-KEY: MC-025 333 :TRACER-BULLET: yes 334 :END: 335 336 - [ ] Add all three useMachine calls to Map 337 - [ ] Render all marker types 338 - [ ] Verify no conflicts 339 - [ ] Commit: "feat: integrate all three transport patterns" 340 341 ** Issue 026: Create Unified Sidebar 342 :PROPERTIES: 343 :RADICLE-KEY: MC-026 344 :TRACER-BULLET: yes 345 :END: 346 347 - [ ] Combine all state displays in one sidebar 348 - [ ] Add connection status indicators 349 - [ ] Show asset counts by category 350 - [ ] Unified telemetry panel 351 - [ ] Commit: "feat: create unified sidebar" 352 353 ** Issue 027: Add Final Visual Polish 354 :PROPERTIES: 355 :RADICLE-KEY: MC-027 356 :TRACER-BULLET: yes 357 :END: 358 359 - [ ] Add connection status icons (green/red) 360 - [ ] Improve telemetry panel styling 361 - [ ] Add loading states 362 - [ ] Create DefaultCatchBoundary error component 363 - [ ] Create NotFound component 364 - [ ] Wire errorComponent and notFoundComponent into root route 365 - [ ] Verify responsive layout 366 - [ ] Commit: "refactor: add visual polish" 367 368 * Future Enhancements 369 370 ** Issue 028: Marker Clustering 371 :PROPERTIES: 372 :RADICLE-KEY: MC-028 373 :TRACER-BULLET: yes 374 :END: 375 376 - [ ] Research marker clustering options 377 - [ ] Implement for performance 378 - [ ] Test with many markers 379 - [ ] Commit: "feat: add marker clustering" 380 381 ** Issue 029: Filter by Asset Type 382 :PROPERTIES: 383 :RADICLE-KEY: MC-029 384 :TRACER-BULLET: no 385 :END: 386 387 - [ ] Add toggle controls 388 - [ ] Filter visible markers 389 - [ ] Update counts display 390 - [ ] Commit: "feat: add asset type filters" 391 392 ** Issue 030: Historical Tracking 393 :PROPERTIES: 394 :RADICLE-KEY: MC-030 395 :TRACER-BULLET: no 396 :END: 397 398 - [ ] Store position history 399 - [ ] Draw path trails 400 - [ ] Add timeline control 401 - [ ] Commit: "feat: add historical tracking" 402 403 ** Issue 031: Alert Export 404 :PROPERTIES: 405 :RADICLE-KEY: MC-031 406 :TRACER-BULLET: no 407 :END: 408 409 - [ ] Implement export function 410 - [ ] Support CSV/JSON formats 411 - [ ] Add download button 412 - [ ] Commit: "feat: add alert export" 413 414 ** Issue 032: Multi-Region Support 415 :PROPERTIES: 416 :RADICLE-KEY: MC-032 417 :TRACER-BULLET: no 418 :END: 419 420 - [ ] Add region selector 421 - [ ] Change bounding box for OpenSky 422 - [ ] Change SSE URL for different MBTA regions 423 - [ ] Commit: "feat: add multi-region support"