nodes and output
"nodes": { "bg": { "op": "solid", "color": "#fbf6e6" }, "out": { "op": "blur", "input": "@bg", "sigma": 2 }},"output": "@out"Node syntax
Section titled “Node syntax”Each entry is id: { "op": "<op-name>", …fields }. The id is yours; the op name
selects the implementation from the registry (all 82 are in the
node catalog); everything else is that op’s fields.
Ids may contain letters, digits, _ and -, and must not start with a digit.
Function expansion produces ids of the form <call>/<node>, so avoid / in ids
you write yourself.
The order of entries is meaningless. Evaluation order comes from the references. Group and name nodes for a human reader.
Wiring
Section titled “Wiring”A field whose value is "@other" is a connection. What kind of connection it is
depends on the field:
"features": "@water_f" // a Features port"input": "@bg" // a Raster (or Sprite) port"brush": "@pencil" // a Brush port"sigma": "@computed" // a Scalar portThe op declares each port’s accepted kinds, and build_graph checks them — see
ports and types. A numeric field usually accepts
a literal, $param, or @node interchangeably.
Fan-out is free and encouraged: several consumers may reference one node, and it is evaluated once because the cache is content-addressed.
Common shapes
Section titled “Common shapes”A layer. Data always enters through a features node, which is where the
filter and zoom gates live, and is shared by every consumer of that layer:
"roads_f": { "op": "features", "layer": "roads", "filter-expr": ["==", ["get", "kind"], "highway"], "min-zoom": 8 },"roads": { "op": "stroke", "features": "@roads_f", "color": "#333", "width-px": 1.5 }Stacking. Compositing is a blend chain — painter’s algorithm as a graph.
ezu translate emits exactly this from a MapLibre layer list:
"c1": { "op": "blend", "base": "@bg", "over": "@landuse" },"c2": { "op": "blend", "base": "@c1", "over": "@water" },"out": { "op": "blend", "base": "@c2", "over": "@roads" }For many layers at once, stack composites a list in one node.
blend chain — the shape ezu translate emits from an ordered MapLibre layer list.Masking. blend with clip: true clips the result to the base’s alpha —
Photoshop’s clipping mask, and how a fill-pattern gets confined to its polygon.
Toggling a branch. switch selects between two inputs, which is how
--keep-hidden preserves a hidden MapLibre layer without drawing it.
The output
Section titled “The output”"output": "@out"output must resolve to a node whose kind is Raster. Notably:
- A
Spritecannot be the output (it is not canvas-sized) — put it through a placement op first. Features,Brush,Scalar,LabelsandScalarFieldcannot be the output either.color-rampis the usual way to turn aScalarFieldinto aRaster.
Nodes not reachable from output are still validated but never evaluated — handy
for commenting a branch out, cheap to leave in place.
Inspecting a graph
Section titled “Inspecting a graph”ezu graph style.json # Mermaid `graph LR` of the dependenciesezu --verbose tile … # per-node op, cache hit/miss, output shape, durationThe Mermaid diagram is the fastest way into a translated recipe you did not write.
Map renders on this site are made fromOpenStreetMap data viaProtomaps (© OpenStreetMap contributors), elevation from Re:Earth Terrain,Mapterhorn andEGM2008 (NGA), and aerial imagery from GSI Japan(© 国土地理院). The painterly styles use CC0 brushes byDavid Revoy.