Sources
Ops with no upstream input: features bound by the host, synthesized geometry, images, DEM and raster tiles.
12 ops: dem, features, fonts, graticule, icon, image, literal-geometry, point-grid, point-scatter, raster, sprite, tile-bounds.
Ops with no demo image below produce no visible result on their own — they feed other nodes rather than paint.
Sample a host-bound raster DEM as a ScalarField. source names a dem entry in the document’s sources block; omitting it falls back to the document’s only dem source, with a build warning.
| Field | Type | Required | Description |
|---|---|---|---|
max-zoom |
integer (0…24) | no | Style-level maximum zoom. Above this zoom the node emits a zero field. |
min-zoom |
integer (0…24) | no | Style-level minimum zoom. Below this zoom the node emits a zero field, as for a tile the source does not have. |
source |
string | no | Name of a dem source in the document’s sources block. Omitting it resolves to the only such source and warns at build time. |
features
Section titled “features”Sample features from a host-bound feature layer. source names an mvt/pmtiles/geojson entry in the document’s sources block (omitting it resolves to the only such source, with a build warning); layer selects a layer within that source (for geojson, the layer name equals the source name).

| Field | Type | Required | Description |
|---|---|---|---|
filter-expr |
— | no | A MapLibre filter expression (JSON array, e.g. [“all”, [“==”, [“get”, “class”], “primary”], [“has”, “name”]]), evaluated per feature. A feature passes only when the expression is truthy. Supports the full expression language (any/has/comparisons/geometry-type). |
layer |
string | yes | Vector tile layer name within source (e.g. earth, roads). |
max-zoom |
integer (0…24) | no | Style-level maximum zoom. Above this zoom the node emits an empty layer. |
min-zoom |
integer (0…24) | no | Style-level minimum zoom. Below this zoom the node emits an empty layer (the asset is not even loaded). |
min-zoom-field |
string | no | Per-feature property name carrying its data-side min_zoom. Features with <field> > z are dropped. |
source |
string | no | Name of an mvt, pmtiles, or geojson entry in the document’s sources. Omitting it resolves to the only such source and warns at build time. |
stitch |
merge | pieces | $param |
no | Join the layer to its 8 neighbouring tiles, for effects that reach further than the tile’s thin buffer: wide strokes along outlines, large buffers, closings. Each tile contributes only the area it owns, so nothing is drawn twice. merge unions polygons with identical properties so no edge remains where tiles meet; pieces keeps every piece as its tile cut it (cheaper, and identical when the layer is only filled). Costs fetching and decoding up to 8 more tiles for this layer only; a neighbour the host cannot provide falls back to this tile’s own buffer data. Omit to read this tile alone. Read when the graph is built: a $param gives its default. |
The style’s fonts, as named font stacks for text and text-labels (wired to their fonts). Each stack is a fallback chain of font and glyphs sources: the first covering a character shapes it, and outline fonts and SDF glyph stacks mix freely. Glyph ranges are fetched as labels need them. A label node names the stack its labels use in font (or per feature in font-expr).
| Field | Type | Required | Description |
|---|---|---|---|
font-stacks |
object | yes | Stack name → ordered font / glyphs source names. A name of several fonts is written as MapLibre’s text-font joins them, with , (spaces around it are ignored), so a font-expr result or a format section’s text-font finds it. Stacks are numbered in name order, and the number is each stack’s stable id, which the layout cache and the collision tie-break use. |
graticule
Section titled “graticule”Parallels and meridians crossing the tile, as labelled polylines.

label property (35.68°N), so text can annotate them. style| Field | Type | Required | Description |
|---|---|---|---|
axes |
both | parallels | meridians | $param |
no | Which families to emit: parallels of latitude, meridians of longitude, or both. |
extent |
integer (1…∞) | no | Coordinate extent of the emitted geometry, matching the features it is drawn alongside. |
interval-deg |
number | $param | @node |
no | Spacing in degrees, for both axes unless interval-x-deg or interval-y-deg overrides one. Omit to pick one from the zoom along the 30/10/5/2/1 ladder. |
interval-x-deg |
number | $param | @node |
no | Degrees of longitude between meridians, overriding interval-deg on that axis. |
interval-y-deg |
number | $param | @node |
no | Degrees of latitude between parallels, overriding interval-deg on that axis. |
Crop one named icon from a sprite source’s atlas. sprite is an @sprite-source ref (or literal atlas key); name is the icon’s index key. Output is a Sprite at the icon’s atlas pixel size; a name the sheet lacks gives a transparent 1×1 sprite, which draws nothing. To pick an icon per feature, wire a sprite node’s sheet into stamp, line-stamp or text instead.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | — |
sprite |
string | yes | Asset reference (@name) or literal path. |
Image asset source. src is an @asset ref or a literal path/name resolved by the host’s AssetLoader. Output preserves the source dimensions.
| Field | Type | Required | Description |
|---|---|---|---|
src |
string | yes | Asset reference (@name) or literal path. |
literal-geometry
Section titled “literal-geometry”Literal geometry source. Coordinates are tile-local pixels in [0, extent].
| Field | Type | Required | Description |
|---|---|---|---|
extent |
integer (1…∞) | no | — |
lines |
array of array of array of number | no | — |
points |
array of array of number | no | — |
polygons |
array of object | no | — |
point-grid
Section titled “point-grid”Regular lattice of points covering the tile.

| Field | Type | Required | Description |
|---|---|---|---|
anchor |
tile | world | $param |
no | — |
extent |
integer (1…∞) | no | — |
offset-x |
number | $param | @node |
no | — |
offset-y |
number | $param | @node |
no | — |
spacing |
number (0…∞) | $param | @node |
no | Grid pitch in extent units, not pixels — extent below is the coordinate space (4096 by default), so a 512 px tile fits 8 points at spacing: 512. Paint ops downstream take pixels, so the two do not match. Required unless both spacing-x and spacing-y are given. |
spacing-x |
number (0…∞) | $param | @node |
no | Spacing along x in extent units, overriding spacing on that axis. |
spacing-y |
number (0…∞) | $param | @node |
no | Spacing along y in extent units, overriding spacing on that axis. |
stagger |
number | $param | @node |
no | Shift every other row sideways by this fraction of spacing-x. 0.5 puts each row’s points halfway between the row above’s — the centres of a running brick bond, or a triangular lattice. |
point-scatter
Section titled “point-scatter”Random points at a given mean spacing, covering the tile. Where point-grid puts exactly one point in the middle of every cell, this one draws a count per cell — 0 to 3, averaging 1 — and places each point at a random spot inside it, so the set has the clumps and gaps of a real random scatter and no residual pitch. Reach for point-grid when the regularity is the point (a halftone screen, a tiling of panes to fracture) and for point-scatter when it is the enemy (stipple, foliage, grain, scattered symbols). Jittering a point-grid is not a substitute: one point per cell means an even density, and the lattice frequency stays plainly visible.
| Field | Type | Required | Description |
|---|---|---|---|
anchor |
tile | world | $param |
no | world indexes the cells off global (0, 0), so adjacent tiles agree on the points they share and the scatter is seamless — the usual choice. tile indexes off the tile’s own corner, giving every tile the same point set and a visible seam. |
extent |
integer (1…∞) | no | — |
seed |
integer (0…∞) | no | Optional explicit u32 seed. Change it to get a different scatter at the same spacing, or to keep two point-scatter nodes from landing on each other. Default: a fixed constant, so the pattern is stable across tiles and runs. |
spacing |
number (0…∞) | $param | @node |
no | Mean spacing in extent units, not pixels — one point per spacing × spacing cell on average. extent below is the coordinate space (4096 by default), so a 512 px tile averages 8 points across at spacing: 512. Paint ops downstream take pixels, so the two do not match. Required unless both spacing-x and spacing-y are given. |
spacing-x |
number (0…∞) | $param | @node |
no | Spacing along x in extent units, overriding spacing on that axis. |
spacing-y |
number (0…∞) | $param | @node |
no | Spacing along y in extent units, overriding spacing on that axis. |
raster
Section titled “raster”Sample a host-bound RGBA tile pyramid (satellite imagery, pre-rendered basemaps) as a canvas-padded Raster. source names a raster entry in the document’s sources block; omitting it falls back to the document’s only raster source, with a build warning. The colour fields adjust the imagery with the formulas of MapLibre’s raster layer, applied in its order: hue, saturation, contrast, then the brightness range. At their defaults the pixels pass through unchanged.
| Field | Type | Required | Description |
|---|---|---|---|
brightness-max |
number (0…1) | $param | @node |
no | What a channel at 1 becomes (MapLibre’s raster-brightness-max). |
brightness-min |
number (0…1) | $param | @node |
no | What a channel at 0 becomes; the range 0..1 is mapped linearly onto brightness-min..brightness-max (MapLibre’s raster-brightness-min). |
contrast |
number (-1…1) | $param | @node |
no | Scales each channel around mid-grey: by 1 + contrast below 0, by 1 / (1 - contrast) above it (MapLibre’s raster-contrast). |
hue-rotate-deg |
number | $param | @node |
no | Turns every hue by this many degrees around the grey axis, keeping each pixel’s channel sum (MapLibre’s raster-hue-rotate). |
max-zoom |
integer (0…24) | no | Style-level maximum zoom. Above this zoom the node emits transparent pixels. |
min-zoom |
integer (0…24) | no | Style-level minimum zoom. Below this zoom the node emits transparent pixels, as for a tile the source does not have. |
opacity |
number (0…1) | $param | @node |
no | Multiplies the imagery’s alpha (MapLibre’s raster-opacity). |
saturation |
number (-1…1) | $param | @node |
no | Moves each channel towards (below 0) or away from (above 0) the mean of the pixel’s channels. -1 is grey; towards 1 the push grows without bound (MapLibre’s raster-saturation). |
source |
string | no | Name of a raster source in the document’s sources block. Omitting it resolves to the only such source and warns at build time. |
sprite
Section titled “sprite”A sprite source’s whole sheet — its atlas and name → rect index — for the ops that pick an icon per feature by name: stamp and line-stamp take it on sheet, text and text-labels on icon-sheet. sprite is an @sprite-source ref (or literal atlas key). To place one named icon, use icon instead.
| Field | Type | Required | Description |
|---|---|---|---|
sprite |
string | yes | Asset reference (@name) or literal path. |
tile-bounds
Section titled “tile-bounds”Tile-filling rectangle polygon source. cover: canvas grows it over the padded canvas, so geometry built from it — Voronoi cells, hatch lines — reaches past the tile’s edge and neighbouring tiles build the same shapes along their shared border.

| Field | Type | Required | Description |
|---|---|---|---|
cover |
tile | canvas | $param |
no | tile is the visible tile exactly; canvas adds the canvas padding on every side. |
extent |
integer (1…∞) | no | — |
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.