An interactive, weighted force-directed graph (D3.js) of the KERI value system. The data comes from a published Google Sheet (CSV) that evolved out of keri-foundation/CONF26-subtitles#21.
The dataset is work in progress — the graph is built to be easy to update as terms are added to the sheet.
Live: https://blockchainbird.github.io/KERI-value-system-visualisation/
npm install
npm run dev # opens a dev server, usually http://localhost:5173
npm run fetch-data # re-download the sheet CSV and regenerate the dataset
npm run fetch-clips # re-parse the SEGMENTS sub-issues and regenerate the clips
npm run build # production build in dist/
npm run live # build and rsync to dwarshuis.com/test/KERI-value-system-visualisation/- Nodes are the tags from the sheet (SECUFIRST, SAFETY, RECOUPEERS, …), colour-coded by their Type column: KERISuite unique values, more common values, and common absent values.
- Node size reflects the node's weight. The fetch script derives it from the number of connections (3–9); it stays editable per node in the UI.
- Link thickness reflects the link's weight (1–3). Links come from the sheet's Vertices tab (Source, Destination, Connection Context, Personas) and are drawn as arrows from source to destination. Hover a link to read its connection context. The Nodes tab's "Vertices / referenced tags" column is used only as a fallback for edges not yet listed on the Vertices tab.
- Hover a node to see its description and highlight its neighbours. Drag nodes, pan and zoom freely, and use Fit to re-centre.
Use the slide-in editor (left-edge Editor tab, bottom-right Editor button, or click a node):
- Nodes — select a node (dropdown or click in the graph) to edit its id, label, group,
weight, tag (
conscientious/mature), and description.+adds a node,−deletes the selected node with its links. - Links — the list shows the selected node's vertices (or all vertices when nothing is
selected), including connection context and personas from the Vertices tab. Change a
link's weight inline or delete it with
×. Add new links via the source → target dropdowns, with optional context and personas. Click a graph edge to jump to that vertex. - All edits update the graph live.
- Save… writes the current graph as JSON using the File System Access API
(
showSaveFilePicker); browsers without it (Firefox, Safari) fall back to a regular download. - Load… opens a JSON file from disk (
showOpenFilePicker, with an<input type="file">fallback) and validates it before rendering. - Reset restores the bundled default dataset.
npm run fetch-data downloads the published Nodes and Vertices tabs and regenerates
src/data/keri-values.json. Only rows whose Status is Active are processed; other
statuses (for example Inactive) are skipped. It parses each node's Tag, Description, and Type;
extracts {conscientious} / {mature} markers into the node's tag field; builds one directed
link per Vertices-tab row (Source → Destination, with Connection Context and Personas); adds any
Nodes-tab references that are not yet in Vertices; and derives node weights from
connectivity. New Type values in the sheet automatically become new groups with a fallback
colour. Manual weight tweaks made in the edit panel live in the saved JSON files, so re-running
the script overwrites only the bundled default dataset.
Each value node can be illustrated by clips from the KERICONF26 talks. The clips live in a
separate file, src/data/keri-clips.json, generated by npm run fetch-clips from the
"SEGMENTS …" sub-issues of
keri-foundation/CONF26-subtitles#21.
The script:
- fetches all sub-issues via the GitHub API and matches each one to its talk in the video
gallery's
site.json(fuzzy title matching, so renamed issues still resolve); - parses the timestamped segment lines (
17:49 - 18:46 …,00:02:13 …, ranges or bare start times — a missing end time runs to the next segment or 60 seconds); - extracts the value tags mentioned inline (including common misspellings like
VERNOVALorHARDPROB1ST, normalised via an alias table) and keeps only tagged segments; - emits clips in the same spirit as the gallery's
topClipsmechanism (videoTitle,speaker,talk,start,end,quoteplustags).
In the app, selecting a node shows its clips in the Clips panel; each entry deep-links into
the video gallery using its hash mechanism
(<galleryUrl>#<videoId>&t=<start>&e=<end>&from=<thisPageUrl>), which opens the talk at the
right moment and stops at the end of the clip. The gallery reads from (falling back to
document.referrer) and shows a link back to this page. The gallery base URL is set in
scripts/fetch-clips.mjs (GALLERY_URL) and stored in the JSON's meta.galleryUrl.
The graph tooltip also shows each node's clip count.
To attack the market-penetration problem (the MARKETPEN "missing value" node), the repo includes a persona-based persuasion kit:
docs/persona-plan.md— six personas (CISO, regulator, developer, business exec, SSI skeptic, end user), each mapped to the value tags that resonate with them, with key messages, objection handling, tactics, calls to action, and a cross-persona campaign plan.npm run build-personas— scores the value-tagged clips against each persona's tags (speaker diversity enforced, overlapping segments deduped) and regeneratessrc/data/keri-personas.jsonplusdocs/persona-clips.md, a per-persona playlist of gallery clip links (<galleryUrl>#<videoId>&t=<start>&e=<end>). Those URLs use the same clip player as the KERICONF26 video gallery: the talk opens at the start time and stops at the end. No mp4 files are cut.
The default dataset lives in src/data/keri-values.json and is plain JSON:
{
"meta": { "title": "...", "source": "...", "notes": "..." },
"groups": { "human-value": { "label": "Human values", "color": "#f2c14e" }, ... },
"nodes": [ { "id": "SECUFIRST", "label": "SECUFIRST", "group": "unique-value",
"weight": 5, "tag": "conscientious", "description": "..." }, ... ],
"links": [ { "source": "SAFETY", "target": "SECUFIRST", "weight": 1,
"context": "...", "personas": "" }, ... ]
}To add new terms, the preferred route is adding rows to the Google Sheet and running
npm run fetch-data. Alternatively, edit this file directly or use the edit panel and save the
result — a saved file can be re-loaded later or committed back as the new
src/data/keri-values.json. New groups can be added in groups (id, label, colour) and used
immediately by nodes.
| File | Purpose |
|---|---|
src/data/keri-values.json |
The dataset (nodes, links, groups, metadata) |
src/data/keri-clips.json |
Video clips per value tag (generated from the sub-issues) |
scripts/fetch-data.mjs |
Regenerates the dataset from the published sheet CSV |
scripts/fetch-clips.mjs |
Regenerates the clips from the SEGMENTS sub-issues |
src/graph.js |
D3 force simulation and rendering |
src/editor.js |
Edit panel (node/link CRUD) |
src/fileio.js |
HTML5 file save/load with validation |
src/main.js |
Wiring, legend, file buttons |