Loading data
A layer draws whatever its source points at. Most maps load a GeoJSON file that sits on the same site as the page: one you drew on geojson.io, exported from QGIS, or downloaded from an open-data portal. This guide starts there, then covers files on other sites, points written in the YAML, and sources shared between layers.
Load a file from your site
Section titled “Load a file from your site”-
Put the GeoJSON file in your site: in a
data/folder next to your HTML page, or inpublic/data/in an Astro or Vite project. To follow along, download cities.geojson (five US cities, each with anameand apopulation). -
Point a source’s
url:at it:map.yaml type: mapid: citiesconfig:center: [-97, 38]zoom: 2.4mapStyle: "https://tiles.openfreemap.org/styles/liberty"layers:- id: citiestype: circlesource:type: geojsonurl: "/data/cities.geojson"paint:circle-radius: 8circle-color: "#e63946"circle-stroke-width: 2circle-stroke-color: "#ffffff" -
Open the page through a web server (
npx serve,astro dev, or your host). You should see five red dots across the United States:
The file can hold a FeatureCollection, a single Feature, or a bare
geometry ({"type": "Polygon", …}); a single feature or geometry is read as
a one-feature collection.
How paths are read
Section titled “How paths are read”/data/cities.geojsonstarts at the site root. In Astro,public/is the root, sopublic/data/cities.geojsonis/data/cities.geojson.data/cities.geojson(no leading slash) starts at the folder of the web page, not of the YAML file. A map atmaps/city.yamlshown onindex.htmlloadsdata/cities.geojsonfrom besideindex.html.- On a site published under a subpath, such as a GitHub Pages project
site at
https://<user>.github.io/<repo>/, give<ml-map>abase="/<repo>/"and keep the paths as they are. The Astro components set it for you. See Publishing & subpaths.
When a file doesn’t load, the map still draws and a notice lists the problem,
for example “Data file /data/citys.geojson didn’t load (404 Not Found), so
layer cities has no data”, followed by the address the browser tried.
Load a file from another site
Section titled “Load a file from another site”A full URL works the same way. The USGS earthquake feeds are a good test, because their server allows other sites to read them:
type: mapid: earthquakesconfig: center: [-120, 37] zoom: 4 mapStyle: "https://tiles.openfreemap.org/styles/liberty"layers: - id: earthquakes type: circle source: type: geojson url: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson" paint: circle-radius: 5 circle-color: "#ef4444" circle-opacity: 0.7When the other site blocks the request (CORS)
Section titled “When the other site blocks the request (CORS)”A browser only reads a file from another site if that site allows it (CORS). When it doesn’t, the console shows a CORS error and the layer stays empty. You can’t fix that from your page. Download the file and serve it from your own site instead, or ask the data provider whether they offer a CORS-enabled address. For data that changes, a small proxy on your own server is the other option.
Write a few points in the YAML
Section titled “Write a few points in the YAML”For a handful of places you type by hand, skip the file. locations: takes a
list of points, each with coordinates (longitude first) and an optional
name and description:
type: mapid: stopsconfig: center: [-73.98, 40.75] zoom: 12 mapStyle: "https://tiles.openfreemap.org/styles/liberty"layers: - id: stops type: circle source: type: geojson locations: - coordinates: [-74.00, 40.73] name: "Stop A" - coordinates: [-73.96, 40.77] name: "Stop B" paint: circle-radius: 7 circle-color: "#2563eb"The same shorthand exists for one point, one polygon and one line. Each takes
the place of url: or data: on a geojson source, and its name and
description become the feature’s properties:
| Key | Draws | coordinates |
|---|---|---|
location: | one point | [lon, lat] |
locations: | many points | one coordinates per list item |
region: | a polygon | a list of rings: [[[lon, lat], …]], first point repeated last |
route: | a line | a list of at least two points: [[lon, lat], …] |
When the features need other properties (a population for a popup, a
category to colour by), write the GeoJSON itself under data::
source: type: geojson data: type: FeatureCollection features: - type: Feature geometry: { type: Point, coordinates: [-74.006, 40.7128] } properties: { name: "New York", population: 8336817 }Past a few dozen features, a file is easier to edit and keeps the YAML readable.
CSV and spreadsheets
Section titled “CSV and spreadsheets”CSV files (including a Google Sheet published as CSV) aren’t supported: a
layer whose url points at one shows “CSV files aren’t supported” on the map.
Convert the table to GeoJSON first, for example by opening it in
geojson.io or QGIS and saving it as GeoJSON, then point
url at the .geojson file.
Share one source between layers
Section titled “Share one source between layers”When several layers draw the same data (a fill and its outline, points and
their labels), define the source once under sources: and name it from each
layer:
type: mapid: cities-labelledconfig: center: [-98.5, 39.8] zoom: 3 mapStyle: "https://tiles.openfreemap.org/styles/liberty"sources: cities: type: geojson url: "/data/cities.geojson"layers: - id: city-dots type: circle source: cities paint: circle-radius: 6 circle-color: "#e63946" - id: city-names type: symbol source: cities layout: text-field: ["get", "name"] text-offset: [0, 1.2]The file is downloaded once, and a live named source is
polled once for all the layers that use it. A source written on a layer
(source: { type: geojson, … }) belongs to that layer alone; the two forms
mix freely in one document. A layer whose source: names a source the
document doesn’t define fails validation at that line, with a “did you mean”.
Cluster many points
Section titled “Cluster many points”Thousands of points in one place hide each other. With cluster: true the
source groups nearby points into one feature per group, and splits them
again as the reader zooms in. A named source lets three layers draw the
groups, their counts and the single points:
type: mapid: clustered-earthquakesconfig: center: [-120, 37] zoom: 3 mapStyle: "https://tiles.openfreemap.org/styles/liberty"sources: earthquakes: type: geojson url: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson" cluster: true clusterRadius: 50 # pixels: points this close are grouped clusterMaxZoom: 14 # from zoom 15, every point is drawn alonelayers: - id: clusters type: circle source: earthquakes filter: ["has", "point_count"] paint: circle-color: "#3b82f6" circle-opacity: 0.8 circle-radius: ["step", ["get", "point_count"], 20, 100, 30, 750, 40] - id: cluster-count type: symbol source: earthquakes filter: ["has", "point_count"] layout: text-field: "{point_count_abbreviated}" text-size: 12 - id: unclustered type: circle source: earthquakes filter: ["!", ["has", "point_count"]] paint: circle-radius: 6 circle-color: "#ef4444"- A cluster is a feature with a
point_countproperty (andpoint_count_abbreviated, such as “1.2k”).["has", "point_count"]picks out the clusters;["!", ["has", "point_count"]]the single points. - The label layer has no
text-font, so it uses the basemap’s font. If you name a font, it must be one the basemap provides (Layers › Labels). clusterPropertiesadds totals to each cluster, such as the largest magnitude in it. Every clustering key is in the sources reference.
To zoom into a cluster when it’s clicked, see the gallery’s Create and style clusters.
Other kinds of data
Section titled “Other kinds of data”- Vector tiles:
type: vectorwith a TileJSONurl:or atiles:template (https://…/{z}/{x}/{y}.pbf). Each layer then names thesource-layer:it draws. See Add a vector tile source. - Raster tiles and WMS:
type: rasterwith atiles:template andtileSize: 256. See Add a raster tile source and Add a WMS source. - Large files (tens of megabytes and up, imagery, elevation): PMTiles, FlatGeobuf, GeoParquet and Cloud Optimized GeoTIFF read only the part in view. See Large data.
- Data that changes: see Live data.
Which source type fits which data, elevation and image overlays included, is in Sources & layers. Every source type and key is in the sources reference.
Caching
Section titled “Caching”Each map keeps a file it downloaded in memory for five minutes, so layers
that load the same URL fetch it once. The memory is cleared when the page
reloads. cache: { ttl: 60000 } on a source changes the time (in
milliseconds), and cache: { enabled: false } turns it off.
Know when the data has loaded
Section titled “Know when the data has loaded”To do something when a layer’s data arrives or fails (update a count,
show a message), listen for <ml-map>’s ml-map:layer-data-loaded and
ml-map:layer-data-error events; see
<ml-map> events. With the
JavaScript API, the same moments are
renderer.on("layer:data-loaded", …) and renderer.on("layer:data-error", …).
Troubleshooting
Section titled “Troubleshooting”Troubleshooting covers maps that don’t show at all. For a layer that stays empty, read the map’s notice:
- “didn’t load (404 Not Found)”: the path is wrong for the page. Check the address the notice says the browser tried, and the path rules above.
- “it isn’t JSON — a wrong path often returns a web page instead”: the same problem on a host that answers a missing file with a page.
- “it is JSON but not GeoJSON”: the file has no
"type": "FeatureCollection"(orFeature, or a geometry). An API response often wraps the GeoJSON in another object; pointurl:at an address that returns the GeoJSON itself. - “pages opened from a file (file://) can’t load data files”: open the page through a web server instead of double-clicking it.
- A CORS error in the console: see above.
- “CSV files aren’t supported”: see CSV and spreadsheets.
Next steps
Section titled “Next steps”- Layers & styling: draw the data as circles, lines, fills and labels.
- Popups, hover & controls: show a feature’s properties when it’s clicked.
- Large data: files too big to download whole.
- Basic map: a complete map of five cities with popups.
- Gallery: Draw GeoJSON points, Add a GeoJSON line, Add a GeoJSON polygon.
Loading states
Section titled “Loading states”The “Loading map…” text and aria-busy need no setup; how to restyle or
replace them is in <ml-map> styling hooks.