V1 Web PWA · Surface walkthrough

Nisaba · concept graph

A per-surface walkthrough of the V1 Web PWA customer surface: layout, states, interactions, data, and cross-references.

walked
8sections2 minread

On this page

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-navLSubNav entry "Concept graph" on nisaba.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 topLCustomerNav 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 canvasaspectRatio: 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#

  • LoadedgetNisabaGraph() 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#

  • 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
  • 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#

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