merkelbrot

module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2026 License: MIT

README

merkelbrot

Zoomable, fractal-style visualisation for Merkle DAGs and trees.

Go reference CI Quality gate status Go report card MIT licence

Zooming from a whole Merkle DAG down to the fields inside a single blob

What it is

merkelbrot draws a Merkle DAG as nested circles and lets you zoom through it continuously — from the whole graph, into a commit, into its trees, down to the fields inside a single blob — without ever changing screens. Nesting follows the dominator tree, so a node reachable from several parents is drawn once, in the one place every route to it must pass through, and the remaining edges are reported as reference links. Trees and general DAGs go through the same interface: you describe your own nodes, and the library never assumes where they came from.

Install

go get github.com/danielriddell21/merkelbrot          # graph, layout, proof, scene
go get github.com/danielriddell21/merkelbrot/web      # templ renderer (separate module)

The core is a zero-dependency, standard-library-only module. The renderer is a separate module so importing the core never pulls in templ or anything web.

For the demo binary:

brew install danielriddell21/tap/merkelbrot
# or
go install github.com/danielriddell21/merkelbrot/web/cmd/merkelbrot@latest

Usage

Implement graph.Source over whatever your nodes are, then pack and render:

src := graph.NewMemorySource([]string{"commit"},
	graph.Node[string]{ID: "commit", Kind: "commit", Label: "initial", Children: []string{"tree"}},
	graph.Node[string]{ID: "tree", Kind: "tree", Label: "/", Children: []string{"readme"}},
	graph.Node[string]{
		ID: "readme", Kind: "blob", Label: "README.md",
		Payload: []graph.Field{{Key: "size", Value: "184 B"}},
	},
)

g, err := graph.New(src)
if err != nil {
	log.Fatal(err)
}

s := scene.Builder[string]{Title: "my graph"}.Scene(layout.Pack(g, layout.Options{}))
if err := web.Render(context.Background(), os.Stdout, s); err != nil {
	log.Fatal(err)
}

That writes one self-contained HTML page — styles, viewer and data inlined — so it opens with no server. A *scene.Scene is plain JSON, so any other front end can consume it instead.

Demo

merkelbrot serve --source git --repo .           # this repository's own object graph
merkelbrot serve --source ledger -n 24           # a generated UK payments ledger
merkelbrot serve --source git --separate-chains  # commits side by side, each holding what it added
merkelbrot export --source git --diff a1b2..c3d4 # what changed between two commits
merkelbrot serve --source git --verify           # flag any object that no longer hashes to its name

Press / in the viewer to find a node by label, ID or hash.

The sources under examples/ double as reference implementations of graph.Source: a git object reader (loose objects and packfiles, standard library only), a generated payments ledger, and a synthetic content-addressed DAG.

Documentation

API documentation, including runnable examples, lives on pkg.go.dev.

Directories

Path Synopsis
examples
gitrepo
Package gitrepo reads a git repository's object graph directly from disk.
Package gitrepo reads a git repository's object graph directly from disk.
ledger
Package ledger generates a deterministic UK payments ledger shaped like a git object graph.
Package ledger generates a deterministic UK payments ledger shaped like a git object graph.
synthetic
Package synthetic generates a deterministic, content-addressed Merkle DAG.
Package synthetic generates a deterministic, content-addressed Merkle DAG.
Package graph defines the plug-in interface that merkelbrot uses to read Merkle DAGs and trees, together with an indexed, immutable view over them.
Package graph defines the plug-in interface that merkelbrot uses to read Merkle DAGs and trees, together with an indexed, immutable view over them.
Package layout turns a Merkle DAG into nested circles that can be zoomed continuously, from the whole graph down to the fields inside a single node.
Package layout turns a Merkle DAG into nested circles that can be zoomed continuously, from the whole graph down to the fields inside a single node.
Package proof computes the Merkle evidence that makes a DAG worth visualising: which nodes justify a leaf's membership of a root, which subtrees two roots have in common, and which stored hashes no longer match their children.
Package proof computes the Merkle evidence that makes a DAG worth visualising: which nodes justify a leaf's membership of a root, which subtrees two roots have in common, and which stored hashes no longer match their children.
Package scene turns a packed graph into a flat, serialisable view model.
Package scene turns a packed graph into a flat, serialisable view model.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL