Architecture Overview
This is the map. It sketches how a GoFish chart goes from a declarative description to an SVG, and points at the essays that cover each part in depth.
A chart is a tree
GoFish is declarative: you never tell it to draw — you describe what the chart is, and the engine works out the rest. That description is an abstract syntax tree of GoFishNodes. Two kinds of node make up the tree:
- Marks — the things you can see:
rect,ellipse,line,area,text. - Graphical operators — composition:
stackX,spread,layer,connect,coord, and so on. An operator arranges its children; it has no appearance of its own.
The modern v3 fluent API — chart(data).flow(...).mark(...) — is sugar. It desugars into exactly this tree, built from the mark and operator factories.
Three passes
Rendering the tree is not one traversal but three, each answering a different question. A node implements only the passes it participates in.
1 · Domain inference. Before anything can be sized, the engine works out the data ranges in play — the domains. GoFish distinguishes a node's underlying space (is this dimension a position, a size, ordinal, undefined?) and infers position and size domains separately. This pass leans on the monotonic algebra to track, symbolically, how each subtree depends on the data — and to prune subtrees that don't depend on it at all.
2 · Layout. With domains known, each node computes its size. Layout dispatches on the underlying-space kind: a SIZE dimension resolves through the monotonic machinery, a POSITION dimension through position scales. Bounding boxes (the bbox model) are the common currency.
3 · Placement & render. Final absolute positions are assigned, and each node emits SVG. Rendering is reactive — it runs through SolidJS — so a chart can update without a full rebuild. The coord operator is the notable special case: it flattens its subtree into a flat, absolutely-positioned list before applying its coordinate transform.
The full, code-level walkthrough of all three passes is Layout & Render Passes.
Cross-cutting machinery
A few systems thread through every pass rather than belonging to one:
- Contexts.
scopeContext,scaleContext,keyContextcarry variable scoping, color/axis scales, and named-element tracking down the tree. - Coordinate transforms.
linear,polar,bipolar,wavy,clock— pluggable mappings from one plane to another, applied during render. - Names & scoping. Marks can be
named and referenced across charts viaselect(); scoping is deliberately hygienic.
Where to go next
- New to the layout model? Read Layout & Render Passes.
- Curious about the type-level tricks? The Monotonic Module.
- Want the design philosophy? Design Philosophy.
