part of the denful ecosystem
Diagram library for den — graph IR construction, filtering, and multi-format rendering of aspect-resolution pipelines.
Den-diagram is organized as a five-stage pipeline. Each stage has a single responsibility and communicates through well-defined data shapes:
graph LR
subgraph den
capture["Capture\n<i>capture.nix</i>"]
end
subgraph den-diagram
graph_["Graph\n<i>context.nix, graph.nix</i>"]
filter["Filter\n<i>filters/</i>"]
render["Render\n<i>mermaid, dot, plantuml, …</i>"]
export["Export\n<i>export.nix, render-infra.nix</i>"]
end
capture -- "trace entries" --> graph_
graph_ -- "graph IR" --> filter
filter -- "pruned IR" --> render
render -- "source strings" --> export
export -- ".md, .svg" --> out(("output"))
style den fill:#2d333b,stroke:#768390,color:#adbac7
style den-diagram fill:#1c2128,stroke:#539bf5,color:#adbac7
style out fill:#347d39,stroke:#46954a,color:#fff
capture ─→ graph ─→ filter ─→ render ─→ export
(in den) ─────────── (in den-diagram) ──────────
| Stage | Module(s) | Input | Output | Responsibility |
|---|---|---|---|---|
| Capture | den.lib.capture (in den) |
Resolved aspect tree | Structured trace entries | Run fx pipeline with tracing handlers, collect events |
| Graph | context.nix, graph.nix |
Trace entries | Format-agnostic graph IR (nodes, edges, entity kinds) | Build graph IR from flat trace entries — no visual concerns |
| Filter | filters/ |
Graph IR | Pruned/reshaped graph IR | Prune, fold, slice, diff — pure transforms over the IR |
| Render | mermaid.nix, dot.nix, plantuml.nix, ... |
Graph IR | Diagram source strings | Emit format-specific text — theme, colors, layout are render-time concerns |
| Export | export.nix, render-infra.nix |
Source strings + pkgs |
Nix derivations (.md, .svg) |
Build derivations via mermaid-cli/graphviz/plantuml, assemble galleries |
The first stage (capture) lives in den because it drives the fx pipeline. Everything after that is den-diagram — pure functions over plain attrsets, with export being the only stage that touches pkgs.
Add as a flake input:
inputs.den-diagram.url = "github:denful/den-diagram";diagram = inputs.den-diagram.lib;
# 1. Capture — runs in den, produces trace data
captured = den.lib.capture.captureWithPathsWith {
classes = [ "nixos" "homeManager" ];
root = den.lib.resolveEntity "host" { inherit host; };
ctx = { inherit host; };
};
# 2. Graph — builds format-agnostic IR from trace entries
g = diagram.context {
entries = captured.entries;
ctxTrace = captured.ctxTrace;
name = host.name;
};
# 3. Render — emit diagram source in any supported format
rendered = diagram.toMermaid g;fleetData = diagram.fleet.of {
hosts = den.hosts;
flakeName = "my-fleet";
};
diagram.toC4Context fleetData;g = diagram.graph.ofNamespace { aspects = den.aspects; };
diagram.toMermaid g;rc = diagram.renderContext {
inherit pkgs;
theme = diagram.themeFromBase16 { inherit pkgs; scheme = "catppuccin-mocha"; };
};
svg = rc.mmdSourceToSvg "my-diagram" (diagram.toMermaid g);| Function | Format |
|---|---|
toMermaid |
Mermaid flowchart |
toDot |
Graphviz DOT |
toPlantUML |
PlantUML |
toC4Component, toC4Container, toC4Context |
PlantUML C4 |
toC4ComponentMermaid, toC4ContainerMermaid, toC4ContextMermaid |
Mermaid C4 |
toSequenceMermaid |
Scope sequence |
toPolicySequenceMermaid |
Policy sequence |
toSankeyMermaid, toFleetSankeyMermaid |
Sankey |
toTreemapMermaid, toFleetTreemapMermaid |
Treemap |
toMindmapMermaid |
Mindmap |
toStateMermaid |
State diagram |
toPipeFlowMermaid |
Pipe data flow |
toScopeTopologyMermaid |
Scope topology |
toFleetDagMermaid |
Fleet DAG |
toJSON |
Graph IR JSON |
Each renderer has a *With variant accepting { theme, mermaidConfig } for customization.
diagram.graph.aspectsOnly g; # aspect hierarchy only
diagram.graph.providersOnly g; # provider tree
diagram.graph.contextOnly g; # context scopes
diagram.graph.simplified g; # fold providers
diagram.graph.classSlice "nixos" g; # single class
diagram.graph.diffClasses g; # class comparison
diagram.graph.filterUserAspects g; # user-declared onlyDen-diagram depends only on nixpkgs.lib. It has no dependency on den's fx pipeline or module system. The dependency is one-directional: den → den-diagram.
den den-diagram
┌───────────────────┐ ┌──────────────────────────────────┐
│ captureWithPaths │─ data ─>│ graph -> format-agnostic IR │
│ captureFleet │ │ filters -> pruned IR │
│ captureAll │ │ renderers -> source strings │
│ │ │ export -> derivations │
└───────────────────┘ └──────────────────────────────────┘