Skip to content

packages · modules · imports · commits · read from this repository at commit 3a01ba5

This repository as graphs ​

Half of this library imports one file. Holochart is 1,025 source modules in 16 packages, joined by 4,212 imports. 511 of the modules import the entry module of core, and the longest chain of package dependencies is 8 packages deep. The charts below are that structure, drawn by the library itself.

22
workspace packages
72 dependencies declared, 27 of them direct
1,025
source modules in 16 packages
4,212 imports between them
511
modules import core/index.ts
50% of all modules
157
commits, Sep 23 – Oct 4, 2026
39 merges, at most 5 lanes

A graph is nodes and the links between them, and a code base is full of them: packages that depend on packages, modules that import modules, commits that have parents, stages that feed stages. Every chart on this page is one of those, read from the Holochart repository by a script and drawn with the graph, chord and graph3d traces of the graph package. They are live: hover a node or a link for what it is, drag to zoom, click a legend entry to hide a group, drag the 3D charts to orbit.

The packages · Inside one package · Across the packages · The history · The pipeline

The packages ​

The monorepo has 22 workspace packages: 16 under packages/, 3 tools, and the docs site, the sandbox and the examples. Their package.json files declare 72 dependencies on each other, and 27 of those are enough to draw: the rest are implied, as holochart → core is by holochart → runtime → core. Every link points down, so what the rest stands on is at the bottom. The longest chain is 8 packages: docs → examples → holochart → traces-graph → traces-3d → traces-basic → runtime → core. 18 of the other 21 packages depend on core, directly or through others.

Loading example…

All 72 declared dependencies cross each other as links. As a matrix they do not: a row per package, and a filled cell where it depends on the package of the column. Rows and columns run from the bottom of the graph up, so every cell is below the diagonal, and a dependency cycle would put one above it. The two long columns on the left are core and render. The longest row is holochart, the bundle, which depends on 14 packages.

Loading example…

The direct dependencies once more, in space: one plane for each of the 8 ranks of the graph, the apps at the top and core and render at the bottom. A package sits above what it depends on. This one has to be turned to be read: several trace packages share a plane, and from most angles one hides another.

Loading example…

Inside one package ​

packages/traces-graph is the package that draws these charts: 103 modules and 328 imports among them. No positions are given here. The force layout pulls modules that import each other together and pushes the rest apart, and the folders come apart almost by themselves: chord/ and data/ hang from the rest by a few links. A node is as large as the number of modules that import it. The largest is layout/types.ts, the contract that every layout implements, with 37 importers. Switch to ForceAtlas2 to see the clusters pulled tighter.

Loading example…

Do the folders match the imports? louvain looks for communities, groups of modules that import each other more than they import the rest, and finds 7. chord/ and data/ are each one community, whole. layout/ is not one: of its 44 modules, those of the subfolders force/, layered/, tree/ and bundle/ each land in a different community. In all, 68 of the 103 modules (66%) are in the community that holds most of their folder, and 232 of the 328 imports stay inside a folder. Switch the colors to see which modules the two groupings disagree about.

Loading example…

The same comparison for every package with at least 20 modules, as modularity: the share of imports that stay inside a group, less what chance would give. The folders of traces-graph score 0.44 and its communities 0.56. traces-stats, with a folder per trace type, has 95% of its modules where most of their folder is. In render it is 56%: the folder primitives/ holds 62 of its 106 modules and splits into several communities. The folders of express and locales score below zero: their imports cross from one folder to another more often than chance would have them.

Loading example…

Across the packages ​

1,211 of the 4,212 imports cross from one package to another, each to the entry module of the package it names. An arc is as wide as what its package imports plus what imports it, and a ribbon has the color of the package that does the importing: 511 modules import core, 312 runtime, 180 render and 151 traces-basic, on which the other trace packages build. core and render import no other package. The imports and the manifests agree: the 56 pairs of packages with an import between them are the 56 dependencies that the packages declare on each other.

Loading example…

Every module and every import at once: 1,025 spheres, 4,212 lines and about 250,000 lines of TypeScript behind them. A plane has no room for this graph; a third dimension gives it some. Each package gathers around its entry module, and the three large spheres in the middle are the entry modules of core, runtime and render. Of the imports, 2,880 bring in values, 1,296 only types, and 36 are import() calls, the chunks that load on demand.

Loading example…

The history ​

157 commits in the 11 days with commits between Sep 23 and Oct 4, 2026, oldest on the left, drawn the way git tools draw them: a lane per line of development, and a link from every parent to its child. 39 commits are merges, the diamonds, with two links coming in. The comb on the left is one pull request after another: a commit or two on a branch, then the merge that brings it in. Towards the end the rhythm changes to long runs of commits on one line, with a second line of work beside them. There were never more than 5 lanes at once, and the busiest day, Oct 3, had 42 commits.

Loading example…

The pipeline ​

What happens to a figure between createChart and the screen, from ARCHITECTURE.md: 9 stages and 11 links. Four stages are pure functions that could run in a worker, two need the GPU, and an interaction sends an edit back through the update planner. That link closes a loop, so the layered layout has to turn it around to keep the others pointing right, and draws it dashed. The two links that leave "Supply defaults" and skip a stage are what an attribute's editType buys: a change to the layout does not run calc again, and a change of style goes straight to the scene.

Loading example…

How each chart is drawn ​

ChartTracePlaced by
Package dependenciesgrapharrangement: 'layered', box nodes, layered.clusters
Dependencies as a matrixheatmaphx.adjacencyMatrix of Express, rows in dependency order
Dependencies in planesgraph3darrangement: 'layered': a plane per rank
Modules of one packagegrapharrangement: 'force', springs or ForceAtlas2
Communitiesgraphthe same, with node.group from louvain
Folders and communitiesscattermodularity of the graph package, as a dumbbell
Imports between packageschorda square matrix, directed, node.group
Every modulegraph3darrangement: 'force' in three dimensions
Commitsgrapharrangement: 'preset': lanes computed, a day axis
Pipelinegrapharrangement: 'layered', rankdir: 'LR', routing: 'orthogonal'

The graph page has every arrangement, and Network graphs the data helpers used here (degrees, connectedComponents, louvain, modularity) and how to choose between a node-link drawing, a chord diagram and a matrix.

Sources ​

Everything on this page is read from the repository itself, at commit 3a01ba5, by node examples/demos/repo-graphs/data/generate.mts: the package.json of every workspace package, the import and export … from statements of every source module under packages/*/src (tests and fixtures left out), read with the TypeScript parser, and git log (hashes, parents, times and subject lines; no names). The script reads the working tree, so modules that were not committed yet are counted. Details: SOURCES.md. Chart sources: examples/demos/repo-graphs.

Released under the MIT License.