---
path: /domains/nyx/observation-log
surface: customer
domain: nyx
auth: signed-in
source: apps/oshun/web/src/app/domains/nyx/observation-log/page.tsx
status: walked
last_walked:
  - 2026-07-02 equipment-boundary addendum — Playwright now opens the
    Observation Log Equipment tab, verifies the four `OBSERVATION_EQUIPMENT`
    fixture profiles, creates a telescope-only profile on
    `/domains/nyx/telescope`, and returns to prove the observation-log equipment
    list is not shared with telescope-control component state. Spec:
    `apps/oshun/web/e2e/nyx-tonight-observation.spec.ts`.
  - '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;
    content re-verified 2026-06-03 against current source'
---

# Nyx · Observation Log — session list

> **Canonical recording surface (P3, 2026-05-25).** This route is the
> CRUD/management entry for the observing journal. The H1 was disambiguated from
> the sister analytics surface
> ([`domains-nyx-observation-log-deep.md`](./domains-nyx-observation-log-deep.md))
> which previously also rendered "Observation Log" as its H1. Both surfaces now
> carry mutually-linking subtitle copy.

## Purpose

Personal sky-observation log — history of sessions, equipment used, conditions
captured, with statistics and a new-entry composer. Wired via
`apps/oshun/web/src/app/domains/nyx/observation-log/page.tsx` ('use client')
which mounts
`<NyxObservationLog eventId={searchParams.get('eventId')} onBack={() => router.back()} />`.
When the route includes `?eventId=...`, the New Entry form carries that context
into the saved observation.

## Entry points

- **Direct URL / bookmark** — yes (signed-in)
- **In-app navigation** — Nyx hub "Observations" sub-nav and event-detail "Log
  observation" shortcut
- **Browser back affordance** — in-component back button calls `router.back()`

## Layout regions

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

- **Header**: back button (`aria-label="Back"`),
  `<h1>Observation Log · session list</h1>` (1.125rem, `NyxObservationLog.tsx`
  ~1318)
- **Stats strip** — computed via `computeSessionStats()` (verify which KPIs
  surface)
- **Tab bar**: six tabs from local `tabs` array — `History` (`BookOpen`),
  `Sessions` (`Calendar`), `New Entry` (`Plus`), `Equipment` (`Telescope`),
  `Conditions` (`Cloud`), `Statistics` (`BarChart3`)
- **Per-tab content**:
  - `history` — chronological list of past observations
  - `sessions` — session-grouped view
  - `new` — form to log a new observation
  - `equipment` — equipment profiles used
  - `conditions` — captured sky conditions
  - `stats` — aggregate metrics

## States

- [ ] **Loading** — bundled fixture data; client-only
- [ ] **History populated** — entries visible
- [ ] **History empty** — verify empty-state copy
- [ ] **New Entry — empty form** — defaults set
- [x] **New Entry — submitted** — entry appears in History and persists to
      `localStorage["oshun.nyx"]` via `useNyxStore`; event-detail handoffs
      retain `eventId` on the saved row
- [ ] **Statistics** — aggregate counts and charts render
- [x] **Equipment fixture profiles** — the Equipment tab renders
      `OBSERVATION_EQUIPMENT` (`8" Dobsonian`, `10x50 Binoculars`,
      `4" Refractor`, `Naked Eye`). These are read-only observation-log
      profiles, not the editable telescope-control profile state.
- [ ] **Offline** — static bundle; works offline

## Interactions

### Header

- [ ] **"Back" button** (icon, `ArrowLeft`) — `onBack` → `router.back()`

### Tab bar (six tabs)

- [ ] **History tab** — sets `tab='history'`
- [ ] **Sessions tab** — sets `tab='sessions'`
- [ ] **New Entry tab** — sets `tab='new'`
- [ ] **Equipment tab** — sets `tab='equipment'`
- [ ] **Conditions tab** — sets `tab='conditions'`
- [ ] **Statistics tab** — sets `tab='stats'`

### History tab

- [ ] **Each observation row** — verify whether row is interactive (detail
      expansion / edit) or read-only

### New Entry tab

- [ ] **Form fields** — verify which fields exist (target, time, equipment,
      conditions, notes)
- [x] **Submit** — writes a normalized observation to `useNyxStore`, closes the
      form, and returns to the History tab
- [ ] **Cancel / Reset** — verify whether such a control exists

### Equipment tab

- [x] **Equipment profile cards** — read-only cards derived from
      `OBSERVATION_EQUIPMENT`; they show usage counts from fixture
      `OBSERVATION_LOGS` and do not add/edit telescope-control profiles.
- [x] **Telescope boundary** — a profile created in `/domains/nyx/telescope`
      remains in that component's `equipmentProfiles` state only and does not
      appear in the observation-log equipment list.

### Conditions tab

- [ ] **Conditions captured per session** — verify display format

### Statistics tab

- [ ] **Each KPI tile** — number + label

## Data & contracts

- **Reads**: bundled fixture observations, persisted local entries from
  `useNyxStore`, owner-scoped BFF rows from `/v1/nyx/observations`, and
  read-only `OBSERVATION_EQUIPMENT` profile fixtures for the Equipment tab
- **Writes**: new observation entries are persisted local-first to
  `localStorage["oshun.nyx"]` and mirrored to `/v1/nyx/observations`; clearing
  local Nyx storage and reopening the log reloads synced rows from the BFF.
  Equipment profiles are not written by this surface.
- **Realtime**: none
- **Caching**: static client bundle
- **Auth/role check**: middleware enforces signed-in for `/domains/*`

## Cross-references

- Deep / detailed variant:
  [`domains-nyx-observation-log-deep.md`](./domains-nyx-observation-log-deep.md)
- Domain hub: [`nyx.md`](./nyx.md) — sub-nav includes "Observations"
- Sibling tools: [`domains-nyx-telescope.md`](./domains-nyx-telescope.md),
  [`domains-nyx-catalogs.md`](./domains-nyx-catalogs.md)
- Component source:
  `apps/oshun/web/src/components/domains/nyx/NyxObservationLog.tsx`

## Automated coverage

- `apps/oshun/web/e2e/nyx-tonight-observation.spec.ts` — event-detail handoff
  into New Entry, BFF POST/GET and local-cleared reload, Home KPI read-back, tab
  bar/heading, and the Observation Log Equipment tab versus Telescope Control
  equipment-profile boundary.
- `apps/oshun/web/e2e/nyx-observations-bff.spec.ts` — field-log BFF auth,
  validation, no-store, defaulting, owner isolation, and durable read-back.

## Open questions / known gaps

- [ ] Document the relationship between `/observation-log` and
      `/observation-log-deep` — why two surfaces; which is canonical for the Nyx
      sub-nav
- [x] Confirm whether new entries persist across reloads — local persistence
      verified 2026-06-23; BFF write/read-back after local storage clear
      verified 2026-06-24
- [x] Verify whether equipment profiles are shared with `NyxTelescopeControl`
      equipment tab — they are not shared. `NyxObservationLog` reads
      `OBSERVATION_EQUIPMENT` from `nyx-extended-simulation`, while
      `NyxTelescopeControl` owns `INITIAL_EQUIPMENT_PROFILES` and user-added
      profiles in local component state.
