- TypeScript 60%
- C# 24.5%
- JavaScript 7.2%
- PowerShell 4.2%
- C++ 4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .voidbot | ||
| benchmarks | ||
| crates | ||
| docs | ||
| notes | ||
| plugins | ||
| schemas | ||
| scripts | ||
| state | ||
| web/norn-viewer | ||
| .gitignore | ||
| AGENTS.md | ||
| Cargo.lock | ||
| Cargo.toml | ||
| FRIENDLINESS_TUNER.md | ||
| Norn.csproj | ||
| package-lock.json | ||
| package.json | ||
| Program.cs | ||
| README.md | ||
| RichSvgRenderer.cs | ||
| TUNING.md | ||
Norn
Rust hybrid Sugiyama / Kamada-Kawai 2D and 3D graph layout solver for Epiphany typed graph state, with React/WASM and C# windows onto the solver.
The solver crate lives in crates/norn-rs. That is Norn's body. The React
viewer in web/norn-viewer is the live browser inspection package for clients
and agents that want to render architecture, dataflow, and typed cross-links
in a UI.
The .NET generator, MSAGL SVG renderer, and MCP server still exist as support tools for note exports, SDK/bridge work, and legacy inspection. They are windows onto the solver, not competing engines. Do not make consumers choose between truths like this repo is a sad little trade show booth.
Eve Plugin Sidecar
crates/norn-eve-plugin is Norn's runtime-independent Eve plugin boundary. Its
default entry point advertises a CultNet RUDP operation endpoint carrying
MessagePack Eve ABI requests. The sidecar owns graph validation, semantic
projection, and solver-backed measurement. It does not own provider state or
renderer projection. Pass --stdio only for local NDJSON debugging.
Owner-published discovery and conformance documents live under plugins/ and
the graph document/layout schemas live under schemas/.
npm run witness:eve-plugin
Rust Solver
cd E:\Projects\Norn
cargo test
The crate is under crates/norn-rs and exports both a normal Rust library and a
cdylib target for the WASM bridge. Solver algorithm work starts there.
React Viewer
cd E:\Projects\Norn\web\norn-viewer
npm install
npm run dev
import { NornViewer } from "@gamecult/norn-viewer";
import type { NornGraphsState } from "@gamecult/norn-viewer";
export function GraphScreen({ state }: { state: NornGraphsState }) {
return (
<NornViewer
state={state}
layoutMode="combined-force"
motion={{ strength: 1.05, flow: 1.1, orbit: 0.85 }}
performance="fast"
/>
);
}
The public viewer API is intentionally coarse:
layoutMode:layered,stress,force, orcombined-forcemotion: viewer-owned force tuning for Rust-solver combined-force layoutsperformance:quality,balanced,fast, or explicitsimulationBudgetMsrealtime knobsselection,focusSelection,expandedNode, and callbacks for app integration- typed state and event payloads
What It Does
The support generator:
- scans markdown notes under a vault folder
- resolves Obsidian wikilinks and regular markdown note links
- optionally starts from an entry note and keeps only reachable notes
- classifies notes into
source-treeandcontrol-flowgraph families - lays out each family as its own graph partition
- reports cross-links that still jump between those families
- runs Microsoft Automatic Graph Layout
- writes:
manifest.jsonsource-tree.svgsource-tree.msagl.svgsource-tree.rich.svgsource-tree.jsoncontrol-flow.svgcontrol-flow.msagl.svgcontrol-flow.rich.svgcontrol-flow.jsoncross-links.jsonwarnings.txt
CLI Usage
Run from source:
dotnet run --project . -- `
--vault-root "E:\Projects\Aetheria-Economy\Aetheria\Source Tree Map" `
--entry-note "Source Tree Map" `
--renderer rich `
--output-dir ".\out\source-tree-map"
After packing as a .NET tool:
norn `
--vault-root "E:\Projects\Aetheria-Economy\Aetheria\Source Tree Map" `
--entry-note "Source Tree Map" `
--renderer rich `
--output-dir ".\out\source-tree-map"
MCP Usage
The MCP server exposes one tool:
generate_obsidian_graph_layout
Run From Source
Use this in an MCP client config when you want to launch the server straight from the repo:
{
"mcpServers": {
"norn": {
"command": "dotnet",
"args": [
"run",
"--project",
"E:\\Projects\\Norn\\Norn.csproj",
"--",
"--mcp"
]
}
}
}
Pack As A .NET Tool
Build the package:
dotnet pack . -c Release -o .\nupkg
Install it from the local package output:
dotnet tool install --global --add-source .\nupkg Norn
Then point your MCP client at the installed command:
{
"mcpServers": {
"norn": {
"command": "norn",
"args": ["--mcp"]
}
}
}
MCP Tool Arguments
vaultRoot: path to the Obsidian vault folderentryNote: optional entry note name or relative note pathoutputDir: optional output directory, defaults to./outlayout:sugiyamaormdsrenderer:msaglorrichincludeUnreachable: keep notes that are not reachable from the entry note
MCP Tool Result
The tool writes manifest.json, primary partition SVGs, raw .msagl.svg variants, custom .rich.svg variants, partition JSON files, cross-links.json, and warnings.txt, then returns:
- output paths for each partition
- seed note IDs used for traversal
- total note and edge counts
- per-partition node and edge counts
- warnings
- the resolved entry note ID, if one was used
Graph Families
By default, notes whose basename contains Control Flow land in the control-flow partition, and everything else lands in source-tree.
You can override that with frontmatter on a note:
---
norn-family: control-flow
---
or:
---
norn-families:
- source-tree
- control-flow
---
Supported keys:
norn-familynorn-familiesgraph-familygraph-families
If your chosen entryNote is itself one of the explicit family roots, the generator also seeds traversal from any sibling family roots it can find.
Source Tree Mapwill also pull inControl Flow MapControl Flow Mapwill also pull inSource Tree Map
That keeps structurally separated note graphs from vanishing just because they no longer link to each other directly.
Layout Modes
sugiyama: layered, better for hierarchy-heavy note treesmds: force-ish spread, better when the graph is cross-linked chaos
mds is the closest MSAGL-native approximation to the Obsidian or Kamada-Kawai vibe. It is not a named Kamada-Kawai mode.
Renderer Modes
msagl: the stock MSAGL SVG, useful as the plain baselinerich: a custom SVG renderer that consumes MSAGL graph geometry and semantic metadata, then draws something with more visual hierarchy and less beige despair
Support Tool: Norn Viewer Demo
The web-side viewer package lives under web/norn-viewer/.
It consumes the typed Norn graph state shape directly:
graphs.architecturegraphs.dataflowgraphs.links
and packages:
- Rust hybrid solver layout through bundled WASM
- zoom and pan
- zoom-gated label and detail pop-in
- node, edge, and code-ref inspection
- typed cross-link browsing between architecture and dataflow
- combined-force motion tuning for clients that want the lively overview
Run it locally with:
cd E:\Projects\Norn\web\norn-viewer
npm install
npm run dev
Notes
- unresolved and ambiguous links are written to
warnings.txt - node IDs in the partition
.jsonfiles are relative note paths without.md - the current implementation estimates label sizes instead of using a platform text measurer, because this is a generator, not a cathedral
source-tree.svgandcontrol-flow.svgare the primary outputs for the selected renderer- raw MSAGL output is always preserved as
*.msagl.svg - the custom renderer currently emits
*.rich.svgfrom MSAGL geometry, not from post-processing the stock SVG