Context. surface customer · domain nisaba · route /nisaba/graph · auth signed-in · source apps/oshun/web/src/app/nisaba/graph/page.tsx
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; content re-verified 2026-06-03 against current source
Purpose#
A concept graph centred on a headword (the fixture centres ἡγεμονικόν), with 17 nodes shown of 412 within 2 hops. Surfaces concepts, teachers, passages, and cross-tradition links in a radial SVG layout.
Entry points#
- Nisaba sub-nav —
LSubNaventry "Concept graph" onnisaba.md - Lexicon cross-link — see
nisaba-lexicon.md - Direct URL / bookmark — yes
Layout regions#
page.tsx is a thin server component: await getNisabaGraph() →
<NisabaGraph data={data} />.
Inside NisabaGraph (nisaba.tsx, line 1381):
- Web shell top —
LCustomerNav active="library" - Header strip — eyebrow row "Nisaba · the concept graph" / "Centred on
ἡγεμονικόν · 17 nodes shown of 412 within 2 hops" / "Stoic + cross-tradition";
LDisplayheadline "The shape of an idea." - Filter toolbar — eyebrow row showing kind toggles + layout controls:
● concepts(accent)● teachers(ink)● cross-tradition(ink2)● passages(muted)- "2 hops · 17 of 412"
- "Layout · radial"
- "Re-centre"
- Graph canvas —
aspectRatio: 1000/640SVG over a dotted-grid background; edges (data.edges.map([a, b, label])) and nodes - Sidebar (right, 320 px) — verify in source: typically node detail + filters
States#
- Loaded —
getNisabaGraph()resolves before render - Centred node — fixture: ἡγεμονικόν; tracked via
find(id) - Visible kinds — concepts (accent), teachers (ink), cross (ink2), passages (muted) — confirm which are toggleable in V1
- Hops — fixture "2 hops · 17 of 412"; verify whether hops selector is interactive
- Layout: radial — verify whether alternate layouts exist
- Reduced motion — composes static SVG; verify any animation keyframes in this view
Interactions#
Header#
-
LDisplayheadline — non-interactive
Filter toolbar#
- Kind toggle (concepts / teachers / cross-tradition / passages) — verify whether the chips toggle node visibility or are visual indicators
- Hops control — verify hop adjustment
- Layout · radial — verify layout switcher
- Re-centre — verify whether the action repositions the graph on the centred node
Graph canvas#
- Node click — opens the node's detail (lexicon for concepts, profile
for teachers, passage for passages, cross-tradition card for
crossnodes) - Edge label — non-interactive eyebrow
- Pan / zoom — verify whether the SVG supports pan/zoom or is static in V1
Sidebar#
- Node detail — populated when a node is selected
- Cross-references — verify list of related passages / teachers
Data & contracts#
- Reads:
getNisabaGraph()from@/lib/lilith-data/nisaba-depth— returnsNisabaGraphData(nodes: NisabaGraphNode[],edges: [from, to, label][], plusGraphNodeKindtyping) - Writes: None.
- Realtime: None.
- Caching: server fetch
- Auth/role check: shell middleware
Cross-references#
- Sibling Nisaba routes:
- Component sources:
apps/oshun/web/src/components/lilith/nisaba.tsx(NisabaGraphline 1381)apps/oshun/web/src/lib/lilith-data/nisaba-depth.ts
- Feature spec:
V1/features.md#nisaba
Open questions / known gaps#
- Confirm which toolbar toggles (kind filters, hops, layout, re-centre) are interactive in V1
- Document the node click contract — which surface each
GraphNodeKindnavigates to - Document the BFF endpoint that hydrates
NisabaGraphDataonce it replaces the local fixture - Verify whether pan/zoom is gated behind a feature flag