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.tsxAbout
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
<NoteGraph
notes={notes}
links={links}
showAllLabels={false}
onSelect={(note) => open(note.id)}
/>Examples
A vault, with two orphans
<NoteGraph notes={notes} links={links} />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'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| notes | Note[] | required | { id, title, group?, size? } and { source, target }. |
| links | ForceLink[] | required | { id, title, group?, size? } and { source, target }. |
| onSelect | (note: Note) => void | — | — |
| selectedId | string | — | — |
| height | number | string | 460 | — |
| showAllLabels | boolean | false | Titles are drawn for hubs and for whatever you are hovering, unless you ask for all of them. |
| labelFrom | number | 4 | Titles 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. |
| orphanLabel | string | 'no links' | — |
| emptyLabel | string | 'This vault has no notes.' | — |
| label | string | 'Note graph' | — |
Types
Note
A vault of linked notes, laid out by force.
| Field | Type | Description |
|---|---|---|
| id | string | — |
| title | string | — |
| group? | string | Colours the node. A folder, a tag, whatever you group by. |
| size? | number | Derived from link count, damped by a square root. Sizing by word count or edit date draws your typing habits instead of your structure. |
Behaviour
| Topic | Detail | Description |
|---|---|---|
| orphans | drawn hollow | A 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. |
| hover | dims the rest | At a few hundred nodes the hairball is unreadable at rest. Focus makes it legible for the cost of one class. |
| layout | settles and stops | From useForceGraph. Deterministic seeding, so a reload is the same picture and a server render matches its hydration. Dragging pins a note. |