---
path: /domains/nyx/moon
surface: customer
domain: nyx
auth: signed-in
source: apps/oshun/web/src/app/domains/nyx/moon/page.tsx
status: walked
last_walked:
  '2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data
  (2xx), console/page-errors, expected content, screenshot verified; live
  screen-reader, touch, offline, and telemetry-delivery checks pending a manual
  AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md'
---

# Nyx · Moon Tracker

## Purpose

Lunar phase tracker — current phase, a monthly phase calendar, eclipse listings,
and a detail tab with ephemeris readings. Wired via
`apps/oshun/web/src/app/domains/nyx/moon/page.tsx` ('use client') which mounts
`<NyxMoonTracker onClose={() => router.back()} />`.

## Entry points

- **Direct URL / bookmark** — yes (signed-in)
- **In-app navigation** — verify Nyx hub link and any "Moon · 84%" chip from the
  Nyx hub or events
- **Browser back affordance** — in-component back button calls `router.back()`

## Layout regions

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

- **Header**: back button (`aria-label="Go back"`), title
  `<h1>Moon Tracker</h1>`
- **Tab bar**: four tabs from `TABS` — `Current Phase`, `Calendar`, `Eclipses`,
  `Details`
- **Per-tab content**:
  - `current` — phase illustration + current illumination data
  - `calendar` — month grid with previous/next month buttons (visible
    `DAY_NAMES = Sun, Mon, Tue, Wed, Thu, Fri, Sat`)
  - `eclipses` — list of upcoming solar and lunar eclipses
  - `details` — additional ephemeris (distance, libration etc.)

## States

- [ ] **Loading** — bundled data; client-only
- [ ] **Default tab** — `Current Phase` (verify initial `tab` state)
- [ ] **Calendar populated** — current month shown with phase icons per day
- [ ] **Previous / Next month** — month switches; verify date arithmetic crosses
      year boundary correctly
- [ ] **Eclipses populated** — list of upcoming eclipses
- [ ] **Eclipses empty** — verify empty-state copy
- [ ] **Offline** — static bundle; works offline

## Interactions

### Header

- [ ] **"Go back" button** (icon, `ArrowLeft`) — calls `onClose` →
      `router.back()`

### Tab bar

- [ ] **Current Phase tab** — sets `tab='current'`
- [ ] **Calendar tab** — sets `tab='calendar'`
- [ ] **Eclipses tab** — sets `tab='eclipses'`
- [ ] **Details tab** — sets `tab='details'`

### Calendar tab

- [ ] **Previous month button** — `onPrevMonth` shifts the month backward
- [ ] **Next month button** — `onNextMonth` shifts the month forward
- [ ] **Day cell** — verify whether tapping a day surfaces details or is
      decorative

### Eclipses tab

- [ ] **Each eclipse row** — verify whether row is interactive (link to a
      detailed view) or read-only

## Data & contracts

- **Reads**: bundled ephemeris / phase / eclipse data inside the component
- **Writes**: none
- **Realtime**: none
- **Caching**: static client bundle
- **Auth/role check**: middleware enforces signed-in for `/domains/*`

## Cross-references

- Domain hub: [`nyx.md`](./nyx.md) — "Moon · 84%" appears in the hub chart
- Sibling tools: [`domains-nyx-solar.md`](./domains-nyx-solar.md),
  [`domains-nyx-solar-system.md`](./domains-nyx-solar-system.md)
- Dashboard widget: [`domains-nyx-widgets.md`](./domains-nyx-widgets.md)
  (`Moon Phase` widget mirrors current phase)
- Component source:
  `apps/oshun/web/src/components/domains/nyx/NyxMoonTracker.tsx`

## Open questions / known gaps

- [ ] Confirm whether the calendar respects per-user observer lat/lng for
      rise/set
- [ ] Verify whether day cells are interactive (the icon usage suggests buttons,
      but the snippet doesn't show a handler)
- [ ] Confirm units shown in `Details` tab (km vs au for distance, deg for
      libration)
