---
path: /nisaba/graph
surface: customer
domain: nisaba
auth: signed-in
source: apps/oshun/web/src/app/nisaba/graph/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; content
  re-verified 2026-06-03 against current source'
---

# Nisaba · concept graph

## 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** — `LSubNav` entry "Concept graph" on
  [`nisaba.md`](./nisaba.md)
- **Lexicon cross-link** — see [`nisaba-lexicon.md`](./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";
  `LDisplay` headline "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/640` SVG 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

- [ ] **`LDisplay` headline** — 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 `cross`
      nodes)
- [ ] **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` — returns
  `NisabaGraphData` (`nodes: NisabaGraphNode[]`, `edges: [from, to, label][]`,
  plus `GraphNodeKind` typing)
- **Writes**: _None._
- **Realtime**: _None._
- **Caching**: server fetch
- **Auth/role check**: shell middleware

## Cross-references

- Sibling Nisaba routes:
  - [`nisaba.md`](./nisaba.md), [`nisaba-compare.md`](./nisaba-compare.md),
    [`nisaba-daily.md`](./nisaba-daily.md),
    [`nisaba-lexicon.md`](./nisaba-lexicon.md),
    [`nisaba-manuscript.md`](./nisaba-manuscript.md),
    [`nisaba-notebook.md`](./nisaba-notebook.md),
    [`nisaba-plan.md`](./nisaba-plan.md),
    [`nisaba-scholar.md`](./nisaba-scholar.md)
- Component sources:
  - `apps/oshun/web/src/components/lilith/nisaba.tsx` (`NisabaGraph` line 1381)
  - `apps/oshun/web/src/lib/lilith-data/nisaba-depth.ts`
- Feature spec: [`V1/features.md#nisaba`](../../../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 `GraphNodeKind`
      navigates to
- [ ] Document the BFF endpoint that hydrates `NisabaGraphData` once it replaces
      the local fixture
- [ ] Verify whether pan/zoom is gated behind a feature flag
