Skip to content

Sources & layers

A map document draws data in two steps. A source says where the data comes from: a GeoJSON file, a tile server, an image. A layer says how to draw one source: as circles, lines, fills or labels. This page explains how the two connect and which page covers each part. For every key with its type and default, see the sources reference and the layers reference.

Define a source once under sources:, then name it from each layer that draws it. Here one week of earthquakes feeds a heatmap when zoomed out and circles when zoomed in:

quakes.yaml
# yaml-language-server: $schema=https://docs.maplibre-yaml.org/schema/latest/map.schema.json
type: map
id: quakes-two-ways
config:
center: [-120, 37]
zoom: 4
mapStyle: "https://tiles.openfreemap.org/styles/liberty"
sources:
quakes: # defined once, downloaded once
type: geojson
url: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson"
layers:
- id: quake-density # drawn first, so it sits underneath
type: heatmap
source: quakes
maxzoom: 7
paint:
heatmap-weight: ["interpolate", ["linear"], ["get", "mag"], 0, 0, 6, 1]
heatmap-radius: 20
- id: quake-points # drawn on top, from zoom 5 in
type: circle
source: quakes
minzoom: 5
paint:
circle-radius: ["interpolate", ["linear"], ["get", "mag"], 1, 3, 6, 18]
circle-color: "#ef4444"
circle-stroke-width: 1
circle-stroke-color: "#ffffff"
One source, two layers: a heatmap zoomed out, circles from zoom 5

Edit this map in the playground

A layer’s source: takes one of three forms:

  • A name (source: quakes) points at an entry under sources:. Every layer that names it shares that one source: the file is downloaded once, and a live source is polled once for all of them. This is the form to use whenever two layers draw the same data. A name the document doesn’t define fails validation at that line, and the message lists the sources the document does define.
  • A source written on the layer (source: { type: geojson, url: … }) belongs to that layer alone. It is the shortest form for a map with one layer per dataset.
  • A reference (source: { $ref: "#/sources/quakes" }) copies the named definition into the layer when the document is read, so each layer gets its own copy rather than sharing one. It is meant for documents that other tools generate. A $ref inside the definition it points at is not followed.

The forms mix freely in one document. Loading data covers named sources step by step.

type: is the kind of data MapLibre draws, not the file format. A FlatGeobuf file is still type: geojson, and a PMTiles archive of vector tiles is still type: vector; the url: tells maplibre-yaml how to read the file (Large data).

Your datatype:Explained in
A GeoJSON file or URL, or points written in the YAMLgeojsonLoading data
A large file of features: FlatGeobuf, GeoParquetgeojsonFlatGeobuf, GeoParquet
Vector tiles, from a tile server or a PMTiles archivevectorLoading data › Other kinds of data, PMTiles
Imagery: raster tiles, WMS, a Cloud Optimized GeoTIFFrasterLoading data › Other kinds of data, COG
Elevation, for hillshading and 3D terrainraster-demLayers › Imagery and elevation, Map documents › Terrain, sky & projection
One picture or video pinned to four cornersimage, videoAnimate a series of images, Add a video
Data that changes while the page is opengeojson with refresh: or stream:Live data

A path without a scheme (data/cities.geojson, /data/cities.geojson) is read relative to the web page, not to the YAML file. The rule covers every address in a document: a source’s url: and tiles:, images:, marker icons, mapStyle, and a story chapter’s pictures and video. On a site served from a subfolder, give the element a base. Details and the notice a wrong path shows: Loading data › How paths are read.

Points, lines and polygons written in the YAML

Section titled “Points, lines and polygons written in the YAML”

A geojson source can take location:, locations:, region: or route: in place of url: or data:, for a few hand-placed features. They are read as ordinary GeoJSON before the document is checked. See Loading data › Write a few points in the YAML.

A layer’s type, source, source-layer, paint, layout, filter, minzoom and maxzoom are MapLibre’s, unchanged: the MapLibre style spec documents every paint and layout property, and Layers & styling shows each layer type. maplibre-yaml adds these keys:

KeyWhat it addsExplained in
interactive:Popups, hover highlights and tooltips, camera moves on clickPopups, hover & controls
classify:Colours or sizes by class, with a legend, without writing the expressionThematic maps & legends
legend:The layer’s own legend entry, or false to leave it outThematic maps › The legend
label:, toggleable:A checkbox in the map’s layer panelLayers › Show a layer only at some zooms
visible:Start the layer hiddenLayers › Show a layer only at some zooms
before:Draw the layer under one of the basemap’s layersLayers › Layer order
effect:An experimental shader effect drawn over the layerEffects

A popup is a layer’s interactive.click.popup: a list of HTML elements filled with the clicked feature’s properties. How to write one, and every kind of item it can hold, is in Popups, hover & controls › Choose what the popup shows. A popup that opens at a fixed place, with no feature under it, is a document’s popups:.

A popup item with format: shows a number in the reader’s language, such as 8,336,817 or 8.336.817. See Popups › Format numbers.

classify: turns a property into classes (your own breaks, breaks computed from the data, or categories), writes the colour expression, and adds the classes to the legend. See Thematic maps & legends.

Layers draw in the order the document lists them, the first at the bottom, and all of them above the basemap. A background layer is no exception: it covers the basemap unless it is translucent or slid under it with before:. To draw a layer under part of the basemap, such as its place names, give before: the id of that basemap layer (Layers › Layer order).

  • A layer whose source: names a source the document doesn’t define fails validation at that line. Check the spelling against sources:; names are case-sensitive.
  • “Source reference not found: #/sources/quake”: the $ref names a source missing from the document’s top-level sources: (a block’s own sources: aren’t searched). mlym validate and the map report it at the $ref line, with the closest name as a suggestion.
  • source: "#/sources/quakes" fails validation: a reference needs the object form, source: { $ref: "#/sources/quakes" }, or the bare name.

The layer-by-layer checks for a map that draws nothing are in Troubleshooting.