Note Graph

A vault of linked notes laid out by force — the Obsidian-shaped view. Nodes are sized by how many links touch them, hovering dims everything outside the neighbourhood, and orphans are drawn hollow rather than hidden.

src/components/ui/note-graph.tsx

About

From the component's own source, where it was written.

A vault of linked notes, laid out by force.

The Obsidian-shaped view: notes as circles, links as lines, and the thing you are looking for found by shape rather than by name.

**Size is degree, not recency or length.** A hub with thirty backlinks is the note the vault is organised around, and it should be the one your eye lands on. Sizing by word count or edit date produces a picture of your typing habits instead of your structure.

**Orphans are drawn, and drawn differently.** A note nothing links to is the most actionable thing this view can surface — it is either miscategorised or forgotten — so hiding unconnected nodes to tidy the picture removes its main use. They sit in a ring at the edge, hollow.

**Hovering dims everything except the neighbourhood.** At a few hundred nodes the hairball is unreadable at rest; focus is what makes it legible, and it costs one CSS class rather than a second layout.

The layout stops once it settles — see useForceGraph. Dragging a note pins it, which is how you pull a cluster apart to read it.

Install

npx astralyx-ui add note-graph

Usage

import { NoteGraph } from '@/components/ui/note-graph'

<NoteGraph notes={notes} links={links} onSelect={(note) => open(note.id)} />

Composer

Change the props and the source below follows.

  • Maps
  • Protocols
  • Practice
  • Safety
  • Ops
Props
tsx
<NoteGraph
  notes={notes}
  links={links}
  showAllLabels={false}
  onSelect={(note) => open(note.id)}
/>

Examples

A vault, with two orphans

API

Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.

NoteGraph

Extends Omit<ComponentProps<'div'>, 'onSelect'>.

PropTypeDefaultDescription
notesNote[]required{ id, title, group?, size? } and { source, target }.
linksForceLink[]required{ id, title, group?, size? } and { source, target }.
onSelect(note: Note) => void——
selectedIdstring——
heightnumber | string460—
showAllLabelsbooleanfalseTitles are drawn for hubs and for whatever you are hovering, unless you ask for all of them.
labelFromnumber4Titles are drawn for hubs and for whatever you are hovering, unless you ask for all of them.
colorFor(group: string) => string—Map a group to a CSS colour.
orphanLabelstring'no links'—
emptyLabelstring'This vault has no notes.'—
labelstring'Note graph'—

Types

Note

A vault of linked notes, laid out by force.

FieldTypeDescription
idstring—
titlestring—
group?stringColours the node. A folder, a tag, whatever you group by.
size?numberDerived from link count, damped by a square root. Sizing by word count or edit date draws your typing habits instead of your structure.

Behaviour

TopicDetailDescription
orphansdrawn hollowA note nothing links to is the most actionable thing the view can surface — either miscategorised or forgotten — so hiding it to tidy the picture removes the point.
hoverdims the restAt a few hundred nodes the hairball is unreadable at rest. Focus makes it legible for the cost of one class.
layoutsettles and stopsFrom useForceGraph. Deterministic seeding, so a reload is the same picture and a server render matches its hydration. Dragging pins a note.