Knowledge Map

The 2D scatter map at /knowledge — zoom, pan, and cluster visualization across the knowledge graph.

Knowledge Map

The knowledge map at /knowledge renders every entity in the graph as a dot on a 2D canvas. Proximity means semantic similarity — neighboring dots share topical content, whether that's "tools that dedupe customer records" or "papers about supply-chain attestation".

Layout pipeline

The map isn't computed in the browser. It's pre-baked from backend embeddings by scripts/build-knowledge-map.py:

  1. Embeddings — 768-dim vectors per entity, fetched from the backend's knowledge proxy
  2. UMAP — reduces 768 → 2 dimensions for the plot
  3. HDBSCAN — clusters at four density tiers so we can show appropriate labels at each zoom level
  4. k-NN — 8 nearest neighbors per entity, used for the hover-connection feature
  5. c-TF-IDF — generates human-readable cluster labels from note text

The output is a single JSON file (frontend/public/knowledge-map.json) served as a static asset — no runtime compute.

Interactive controls

ActionBehavior
Scroll / pinchZoom in and out (uncapped, so you can drill into dense clusters)
Click + dragPan the canvas
Click a dotSelect the entity, open the detail popover, show 8 k-NN neighbors as halos
Click a cluster labelPan + zoom to fit the cluster's extent
?focus={id} query paramDeep-link directly to an entity — the map pans and selects that dot on load

Progressive label density

Labels get crowded at continent-scale zoom. The map cross-fades through four label tiers as the user zooms:

TierWhen shownTypical label
0Fully zoomed out"Entity Resolution", "Blockchain", "Sanctions"
1Medium zoom"ER benchmarks", "Wallet attribution"
2Close zoom"NC Voter 5K", "BPID Benchmark"
3Individual entitiesRepo names, paper titles

The transitions use alpha blending at level boundaries so labels don't snap in or out.

Search integration

The search bar at the top of /knowledge runs against the same backend entity index. Selecting a hit pans the map to the matching dot via ?focus={entityId}. Search and map share state through the useOpenSource hook in frontend/app/knowledge/use-open-source.ts.

Implementation notes

  • Canvas uses a non-passive wheel listener attached via addEventListener — not React's onWheel — so it can preventDefault() and intercept the scroll
  • All useEffect / useRef hooks must live above any if (failed) return null early return, per React rules-of-hooks
  • Label collision detection happens per frame; text extents cached per label to avoid repeated measurements