V1 Web PWA · Surface walkthrough

Nyx · Satellite Tracker

A per-surface walkthrough of the V1 Web PWA customer surface: layout, states, interactions, data, and cross-references.

walked
8sections2 minread

On this page

Context. surface customer · domain nyx · route /domains/nyx/satellites · auth signed-in · source apps/oshun/web/src/app/domains/nyx/satellites/page.tsx

Last walked. 2026-05-29 automated runtime walk (Playwright) — hydration fix verified: 0 page/console errors, render+data OK; live SR/touch/offline/telemetry pending manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md

Purpose#

Satellite tracking surface — live map of currently overhead satellites, pass prediction lookups, Iridium flare events, and Starlink-specific feeds. Wired via apps/oshun/web/src/app/domains/nyx/satellites/page.tsx ('use client') which mounts <NyxSatelliteTracker onBack={() => router.back()} />.

Entry points#

  • Direct URL / bookmark — yes (signed-in)
  • In-app navigation — verify Nyx hub link
  • Browser back affordance — in-component back button calls router.back()

Layout regions#

NyxSatelliteTracker (apps/oshun/web/src/components/domains/nyx/NyxSatelliteTracker.tsx):

  • Header: back button (aria-label="Back"), title <h1>Satellite Tracker</h1> (1.125rem)
  • Tab bar: four tabs from local tabsLive Map (map, Globe), Pass Predictions (passes, Eye), Iridium Flares (flares, Zap), Starlink (starlink, Wifi)
  • Per-tab content:
    • map — live map with satellite positions
    • passes — predicted pass list for the observer
    • flares — Iridium flare event list
    • starlink — Starlink-specific filters and trains

States#

  • Loading — bundled fixture; client-only
  • Default tabLive Map (verify initial tab)
  • Map populated — satellite markers visible
  • Pass predictions populated — upcoming passes listed
  • Pass predictions empty — verify empty-state copy
  • Flares populated / empty
  • Starlink train listed — verify whether a specific train is shown
  • Offline — static bundle; map tiles may fail offline

Interactions#

  • "Back" button (icon, ArrowLeft) — onBackrouter.back()

Tab bar (four tabs)#

  • Live Map tab — sets tab='map'
  • Pass Predictions tab — sets tab='passes'
  • Iridium Flares tab — sets tab='flares'
  • Starlink tab — sets tab='starlink'

Live Map tab#

  • Map provider — verify (Leaflet / Mapbox / SVG)
  • Satellite marker tap — verify behaviour
  • Filter / search — verify any filtering of the visible satellites

Pass Predictions tab#

  • Each pass row — verify whether row is interactive (detail) or read-only
  • Sort / filter — verify sort affordances
  • Event row — read-only metadata

Data & contracts#

  • Reads: bundled fixture inside the component
  • Writes: none
  • Realtime: none in code; verify whether the live-map updates positions on a timer
  • Caching: static client bundle; map tiles depend on provider
  • Auth/role check: middleware enforces signed-in for /domains/*

Cross-references#

Open questions / known gaps#

  • Runtime walk (2026-05-29) — defect FIXED & verified: React 418 hydration mismatch resolved (time-derived values now deferred to a post-mount effect via useClientNow/useIsMounted from @/hooks/useClientTime; for /coordinates the missed RiseSetCalculator site was gated). Re-walked against a fresh build: 0 page errors, 0 console errors, HTTP 200. React error #418; visit https://react.dev/errors/418?a. React error 418 is a hydration mismatch — server-rendered HTML differs from the client (this view renders time/position-dependent content, e.g. new Date()/toLocale*, without suppressHydrationWarning). Fix: compute time-dependent values in an effect or gate with suppressHydrationWarning. Status kept drafted until fixed.
  • Confirm whether the live map is animated (positions advance on a timer) or static
  • Document the map tile provider and offline behaviour
  • Verify whether pass predictions use the user's actual lat/lng or DEFAULT_OBSERVER