Context. surface customer · domain nyx · route /domains/nyx/star-chart · auth signed-in · source apps/oshun/web/src/app/domains/nyx/star-chart/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#
A full-screen interactive horizon planisphere — rendered as a circular sky map
with stars, constellation lines, and planets at the user's default observer
location. Magnitude limit, time offset, and layer toggles let the user explore
what's currently above the local horizon. Wired via
apps/oshun/web/src/app/domains/nyx/star-chart/page.tsx ('use client') which
mounts <NyxStarChart onClose={() => router.back()} />.
Entry points#
- Direct URL / bookmark — yes (signed-in)
- In-app navigation — verify whether the Nyx domain hub or
EventCalendarOverlaylink routes here (cross-route: focused sky chart links fromNyxEventDetailWorkspaceuseevent.skyChartHref) - Browser back affordance — the page mounts
onClose={router.back()}so the in-component back button leaves this surface
Layout regions#
NyxStarChart (apps/oshun/web/src/components/domains/nyx/NyxStarChart.tsx)
renders a top-to-bottom flow inside one container.
- Header: back button (
aria-label="Go back"), LucideStaricon,<h1> Star Chart</h1>, right-aligned location chip (DEFAULT_OBSERVER.namefromnyx-simulation-data) - Controls strip: magnitude limit range slider (
Mag limit: <value>), time offset range slider (Time: Now/+Nh), four toggle buttons (Constellations, Planets, Grid, Labels) - Chart container: SVG planisphere with radial
skyGradbackground, horizon circle, optional altitude grid (30°/60°), azimuth radials, and generated stars / constellation lines / planets - Selected-body popup: appears when a star or planet is tapped — shows RA / Dec, Magnitude, Spectral Class (stars) or Magnitude / Distance / Elongation / Illumination (planets), with close button
States#
- Loading — no async data; client component hydrates with
generateStars/generateConstellations/generatePlanetssynchronously - Populated (default) — magnitude limit 6.0, time offset 0, Constellations + Planets + Grid + Labels all on
- Faint-stars hidden — slider at 0.5 limits visible stars to the brightest
- Time-shifted — slider at +12h / −12h re-projects the sky for that offset
- Below horizon — bodies with altitude ≤ 0 are filtered out; confirm
chart is not empty for
DEFAULT_OBSERVER - Star selected — tapping a star surfaces the popup; tapping the SVG
background clears it (
onClick={() => setSelected(null)}) - Planet selected — same with planet-specific fields
- Error (recoverable) — N/A — pure client computation; verify no throw
paths in
equatorialToHorizontal/computeGMST - Offline — view is static client code with no fetch; renders offline once cached by SW
- Reduced motion — no animations declared; cursor is
crosshairon the SVG
Interactions#
Header#
- "Go back" button (icon button,
ArrowLeft)- Function: calls
onClose→router.back() - Keyboard: Enter activates; focusable
- Screen reader: announces "Go back"
- Function: calls
Controls strip#
- Magnitude limit slider (range input, min 0.5 max 6 step 0.5)
- Function: filters stars by
magnitude <= maxMagnitude - Screen reader:
aria-label="Magnitude limit, currently <value>"
- Function: filters stars by
- Time offset slider (range input, min −12 max 12 step 0.5)
- Function: shifts
computeGMSTreference time; chart re-projects - Screen reader:
aria-label="Time offset, <now|±Nh hours>"
- Function: shifts
- Constellations toggle (button,
Layersicon)- Function: toggles
showConstellations; constellation lines on/off
- Function: toggles
- Planets toggle (button,
Eye/EyeOfficon)- Function: toggles
showPlanets; planet markers on/off
- Function: toggles
- Grid toggle (button)
- Function: toggles
showGrid; altitude rings + azimuth radials on/off
- Function: toggles
- Labels toggle (button)
- Function: toggles
showLabels; star names / planet names on/off
- Function: toggles
Chart#
- SVG sky (
cursor: 'crosshair')- Function: tap empty area clears
selectedbody - Touch target: full chart area
- Function: tap empty area clears
- Star marker tap — sets
selectedto the star; popup appears with its data - Planet marker tap — sets
selectedto the planet; popup appears
Selected-body popup#
- Close button (icon button at top of popup)
- Function: clears
selected
- Function: clears
- RA / Dec row — formatted via
formatRA/formatDec - Magnitude row
- Spectral Class row (stars only) — color-coded via
SPECTRAL_COLORS - Distance row (stars: parsec; planets: au)
- Temperature row (stars only)
- Constellation row (stars only)
- Elongation row (planets only)
- Illumination row (planets only)
Data & contracts#
- Reads: none from network —
generateStars,generateConstellations,generatePlanets,DEFAULT_OBSERVERfromapps/oshun/web/src/lib/nyx/nyx-simulation-data; types fromapps/oshun/web/src/lib/nyx/nyx-types(StarData,PlanetData) - Writes: none
- Realtime: none
- Caching: static client bundle; SW caches the JS and renders offline
- Auth/role check: middleware enforces signed-in for
/domains/*
Cross-references#
- Domain hub:
nyx.md - Sibling Nyx tools:
domains-nyx-telescope.md,domains-nyx-coordinates.md,domains-nyx-time-travel.md - Component source:
apps/oshun/web/src/components/domains/nyx/NyxStarChart.tsx - Simulation data source:
apps/oshun/web/src/lib/nyx/nyx-simulation-data.ts
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/useIsMountedfrom@/hooks/useClientTime; for/coordinatesthe missedRiseSetCalculatorsite 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*, withoutsuppressHydrationWarning). Fix: compute time-dependent values in an effect or gate withsuppressHydrationWarning. Status keptdrafteduntil fixed. - Confirm whether the magnitude/time sliders expose discrete step keyboard arrows correctly (default browser range behavior)
- Document where
DEFAULT_OBSERVERis overridden for per-user lat/lng — page never passes a custom observer prop - Confirm whether the chart supports pinch-zoom on touch or only the
decorative
crosshaircursor - Verify whether the
event.skyChartHreffrom event detail pages targets/domains/nyx/star-chartwith query params, and how those params are consumed (the component takes no props beyondonClose)