---
path: /domains/nyx/solar
surface: customer
domain: nyx
auth: signed-in
source: apps/oshun/web/src/app/domains/nyx/solar/page.tsx
status: walked
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'
---

# Nyx · Solar Activity Monitor

## Purpose

Solar / space-weather dashboard — Kp index, solar wind, IMF Bz, geomagnetic
storm level, aurora probability, plus four tabs for deeper readings on Overview,
Aurora, Flares & CMEs, and Sunspots. Wired via
`apps/oshun/web/src/app/domains/nyx/solar/page.tsx` ('use client') which mounts
`<NyxSolarMonitor 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

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

- **Header**: back button (`aria-label="Back"`), `Sun` icon (`#c89657`),
  `<h1>Solar Activity Monitor</h1>` (1.5rem), right-aligned "Updated <time>"
  - Refresh button (`aria-label="Refresh"`)
- **Summary strip**: five tiles — `Kp Index` (color-coded with `kpLabel`),
  `Solar Wind` (km/s, alert above 600), `IMF Bz` (nT, alert when southward),
  `Storm Level`, `Aurora` (probability percentage)
- **Tab bar**: four tabs (inline array) — `Overview` (`Activity` icon), `Aurora`
  (`Zap`), `Flares & CMEs` (`AlertTriangle`), `Sunspots` (`Sun`)
- **Per-tab content**:
  - `overview` — Kp Gauge + further detail tiles
  - `aurora` — aurora probability & viewing guidance
  - `flares` — recent flares and CME events
  - `sunspots` — current sunspot group data

## States

- [ ] **Loading** — `SOLAR_ACTIVITY_DATA` fixture loaded on mount
- [ ] **Default tab** — `Overview` (verify initial `tab` is `'overview'`)
- [ ] **Refresh clicked** — `handleRefresh` updates `lastUpdated` and jitters
      `kpIndex` (marked `random:legitimate` in source); summary strip re-renders
- [ ] **High storm level** — color shifts via `stormColor()`
- [ ] **High aurora probability (≥ 50%)** — aurora value renders `--l-ok`
- [ ] **Solar wind > 600 km/s** — value renders `--l-alert`
- [ ] **IMF Bz southward (< 0)** — value renders `--l-alert` with "Southward"
      sub-label
- [ ] **Offline** — static fixture; refresh still re-jitters locally

## Interactions

### Header

- [ ] **"Back" button** (icon, `ArrowLeft`) — `onBack` → `router.back()`
- [ ] **"Refresh" button** (icon, `RefreshCw`)
  - Function: `handleRefresh` — re-jitters `kpIndex` and updates `lastUpdated`;
    updates `lastRefresh` timestamp
  - Screen reader: "Refresh"

### Summary strip (read-only tiles)

- [ ] **Kp Index tile** — number + `kpLabel`
- [ ] **Solar Wind tile** — speed + unit
- [ ] **IMF Bz tile** — value + Northward/Southward label
- [ ] **Storm Level tile**
- [ ] **Aurora tile** — probability %

### Tab bar (four tabs)

- [ ] **Overview tab** — sets `tab='overview'`
- [ ] **Aurora tab** — sets `tab='aurora'`
- [ ] **Flares & CMEs tab** — sets `tab='flares'`
- [ ] **Sunspots tab** — sets `tab='sunspots'`

### Overview tab

- [ ] **Kp Gauge** — visual indicator centered in its panel
- [ ] **`<h3>Kp Index</h3>`** panel heading

## Data & contracts

- **Reads**: `SOLAR_ACTIVITY_DATA` fixture inside the component (verify exact
  `SolarActivity` shape)
- **Writes**: none (state is in-memory)
- **Realtime**: none — refresh is manual and jittered locally
- **Caching**: static client bundle
- **Auth/role check**: middleware enforces signed-in for `/domains/*`

## Cross-references

- Domain hub: [`nyx.md`](./nyx.md)
- Sibling tools:
  [`domains-nyx-sky-conditions.md`](./domains-nyx-sky-conditions.md) (aurora
  overlaps with sky conditions),
  [`domains-nyx-solar-system.md`](./domains-nyx-solar-system.md)
- Component source:
  `apps/oshun/web/src/components/domains/nyx/NyxSolarMonitor.tsx`

## Open questions / known gaps

- [x] **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.
- [ ] Document the planned data source for live Kp / solar wind / IMF data (NOAA
      SWPC? component currently mocks via `Math.random()`)
- [ ] Confirm whether Aurora tab surfaces aurora-viewing locations or only
      probability
- [ ] Verify Flares & CMEs tab content (flare class table, CME ETA?)
