The builder pipeline
You start a spec withcreateSpec and fold parts onto it with pipe. Each part is a small tagged object produced by a builder (geom.*, scale.*, coord.*, config, …):
pipe(spec, ...parts) returns a new spec with each part folded in, left to right — it never mutates. Each kind folds in its own way:
Two of those are worth reading twice.
coord overwrites, so piping coord.polar({ innerRadius: 0.5 }) after coord.polar({ theta: 'y' }) leaves you with the inner radius and no theta — pass both params in one call. And a piped styles(...) sits above everything piped before it, so a later stylesheet wins where the two declare the same property.
Because a spec is a plain object, you can build it up conditionally, share fragments across charts, and store or serialize it.
The parts of a spec
A spec brings together these parts. Each has its own page:
Plus configuration (
config) for chart chrome — titles, axes, legend, layout.
Compile, then render
A spec is a description; it isn’t yet pixels. Turning it into a chart happens in two stages, one per package:- Compile (
@graphysdk/viz-engine). The engine takes your spec plus your data and produces aCompiledSpec: scales are resolved to concrete domains, statistics are run, every observation is placed in a normalized[0,1]position space, the stylesheet is validated and itstoken()references are inlined, and guides (axes, legend) are worked out. This stage is pure data-in, data-out — no DOM. It is also what makes a styled spec serializable: paint comes out the far side as plain values. - Render (
@graphysdk/react-renderer). The renderer takes theCompiledSpecand paints it: it lays out pixel rectangles, formats numbers and dates for the locale, picks the light or dark half of every color pair, and wires up hover and animation.
<GraphProvider> does it for you and recompiles when the spec or data change. The colorScheme is resolved as the chart is read rather than at compile time, so switching it costs nothing:
Why the split matters
The split between the two packages shapes how you use the SDK:- Data lives outside the spec. A spec references columns by name; the actual rows are passed to
<GraphProvider>separately. One spec can draw many datasets. - The compiler never formats. It emits raw values and descriptors; the renderer turns them into locale-aware text. That’s why formatting options live on the renderer side.
- Scales are resolved once, at compile time. This is why you declare scales explicitly in the spec — the engine can’t paint a position it was never told how to compute.
@graphysdk/react.
Next
- Scales — the one part you must always declare
- Serializable spec — a spec is plain JSON you can persist and reload

