Upgrading to 0.9
maplibre-yaml 0.9 (@maplibre-yaml/core 0.9, @maplibre-yaml/astro 0.7,
@maplibre-yaml/cli 0.6) adds thematic maps, large-data formats such as
PMTiles and GeoParquet, and map titles, descriptions and translations. Most
maps upgrade with no change to their YAML. This page lists
how to upgrade, the
changes you might notice, and
what is new.
The full list of changes is in each package’s changelog on npm.
How to upgrade
Section titled “How to upgrade”A project keeps the version it was set up with: nothing moves to 0.9 until you change it.
The version is part of the script’s address. Use the current release line
in the register.js line of your page:
<script type="module" src="https://unpkg.com/@maplibre-yaml/core@0.9/register.js"></script>The number after core@ names a release line: the address loads the newest
release in that line, so bug fixes arrive by themselves, but a new line, which
may behave differently, arrives only when you change the number
(Versions in CDN URLs).
A story page (<ml-scrollytelling>) uses the same script.
If you load the JavaScript API from esm.sh, change the number in that address
the same way:
https://esm.sh/@maplibre-yaml/core@0.9?external=maplibre-gl.
Before 1.0, a range such as ^0.8.1 in package.json stays within 0.8.x,
so npm install never moves it to 0.9 by itself. Ask for the latest release:
npm install @maplibre-yaml/core@latestpackage.json then reads "@maplibre-yaml/core": "^0.9.0" (or later).
Upgrade core and the Astro package together (@maplibre-yaml/astro 0.7
requires @maplibre-yaml/core 0.9 or later):
npm install @maplibre-yaml/core@latest @maplibre-yaml/astro@latestpackage.json then reads "@maplibre-yaml/core": "^0.9.0" and
"@maplibre-yaml/astro": "^0.7.0" (or later). Restart astro dev
afterwards.
With npx maplibre-yaml … there is nothing installed to upgrade; write
npx maplibre-yaml@latest … once so npx doesn’t reuse an older copy it
downloaded before. A CLI installed in a project or globally moves with:
npm install --save-dev @maplibre-yaml/cli@latest # in a project: ^0.6.0npm install -g @maplibre-yaml/cli@latest # installed globallyWhat behaves differently
Section titled “What behaves differently”Your YAML keeps working. These are the changes you might see after upgrading, and what to do about each, if anything.
- The legend’s header always reads “Legend”. On a plain map, a custom
legend.titlenow appears as a heading inside the panel instead of replacing the header, matching story legends; a screen reader announces every legend the same way. No change to your YAML. CSS that styled.legend-titleas your title should target.legend-heading. (Legend) - Author hints show only while you develop. The on-page notice keeps
showing failures (a data file that didn’t load, a layer MapLibre rejected)
everywhere, but hints meant for you (a “did you mean”, a key in the wrong
place, coordinates that look written latitude-first) now show only on
localhost, in afile://page and underastro devorvite, not on your published site. Add thedebugattribute (or thedebugprop on the Astro components) to see them on a deployed page; the console always has them. (Reading what the map tells you) - Strings that start with
=in a style value now warn. The format reserves them for a future shorthand:text-field: "=upper({name})"used to draw the text as written and now gets a warning suggesting a MapLibre expression. Text that really starts with=is written["literal", "=…"]. (Strings starting with=are reserved) - A map without a basemap now warns in validation (
mlym validateincluded).<ml-map>already refused such a map with an error card; the warning says so before you load the page. AddmapStyle:underconfig:. - Popup numbers follow the page’s language. A
format: ",.0f"number used to be written in US English everywhere; on a page with<html lang="de">it now reads8.336.817. Name alocalein the format to fix one regardless of the page. (Number formats) boundsaccepts both of MapLibre’s forms, four numbers[west, south, east, north]or two corners[[west, south], [east, north]](the second used to fail). Values that validated before but broke the map, such as a latitude beyond ±90 or three numbers, are now validation errors with the expected order spelled out. (Fit to bounds)fitToon aurl:source opens already framed on the data, with no jump fromcenter/zoom. While the file loads, the map waits up to 1.5 seconds before its first paint; on a slow file it then draws atcenter/zoomand frames the data when it arrives, as before. (Fit to a source’s data)fitTokeeps a margin around the data. Withoutpadding:, the data is framed with a margin (8% of the map’s shorter side, 12 to 48 pixels, plus room for the attribution at the bottom), so circles and icons at its edges are drawn whole instead of cut in half. Writepadding: 0for the exact extent, as 0.8 framed it, or anypadding:of your own. (Fit to a source’s data)- A layer’s own legend entry shows a legend. A layer with
legend: { label, color }used to appear only when the document also had alegend:block; now the map shows a legend for it anyway, as it does for a classified layer. Writelegend: falseat the top level to keep a map without one. (Legend) mlym emitwrites a GeoJSONurl:source asdata: <url>, the way the MapLibre style spec expects, so the exportedstyle.jsonnow loads in MapLibre. A liveurl:source (refresh:,stream:) is reported as acontractwarning instead oflossy. (emit)- A slow map says it is loading. If a map hasn’t drawn after about a
second, a small “Loading map…” appears in its middle until the basemap
draws. A page with its own loading indicator hides it with
ml-map .ml-map-loading { display: none; }. - A layer whose
before:names a layer the map doesn’t have is drawn on top instead of disappearing (MapLibre used to refuse it). While you develop, the author notes suggest the closest layer id. - The CDN script is larger:
register.browser.jsgrows from about 125 KB to about 175 KB gzip, for thematic maps, translations, number formatting and the large-data formats. The format readers themselves are separate files, downloaded only by maps that use them.
What’s new in 0.9
Section titled “What’s new in 0.9”- Thematic maps. A layer’s
classify:block makes a choropleth, graduated symbols or a category map from your data, with a legend generated for it: explicit breaks or quantile, equal-interval and Jenks classes, named colour palettes, rates withnormalize:, and a colour for missing values. See Thematic maps & legends and the thematic maps example. - Large data from YAML alone. PMTiles, FlatGeobuf, GeoParquet and Cloud
Optimized GeoTIFF (COG) files, read in parts straight from a static host
such as GitHub Pages, and a whole basemap from one Protomaps
.pmtilesfile with no API key (mapStyle: data/city.pmtilesis enough). See Large data: PMTiles, FlatGeobuf, GeoParquet & COG. - Accessible, translated maps. A document’s
title:anddescription:name and describe the map for screen readers;locale:translates every piece of text the library puts on the map; popup numbers useIntl.NumberFormatoptions. See Accessibility & languages. - Smaller conveniences:
fitTo: tracts, just the source name, as shorthand forfitTo: { source: tracts }.legend: falseon a layer keeps it out of the legend.- The
debugattribute on<ml-map>and<ml-scrollytelling>(and thedebugprop on the Astro components) shows author hints on a published page. - On a narrow map, a legend and a layer panel in two corners of the same edge no longer overlap, and a story’s pinned legend no longer covers the map’s notice.
mlym validateprints notes (ℹ note) that explain how a valid value is read, such as a basemap written as just a.pmtilesfile. Notes are not warnings: the file still reads✓ valid, and--strictnever fails on them.mlym init --template basicand--template storyload core at the release line the CLI was built with, so a new project gets the features these docs describe.
Something broke?
Section titled “Something broke?”See Troubleshooting. If a map that worked on 0.8 stops working on 0.9 and the notes above don’t explain it, please open an issue with the YAML and what you see.
Older releases
Section titled “Older releases”Moving a project from an older line, such as 0.5, straight to 0.9? Read the notes for each line you skip, oldest first. Each package’s changelog on npm has the full list.
Upgrading to 0.6
Section titled “Upgrading to 0.6”Three behaviour changes matter when you move to 0.6:
!htmlin popups is trust-gated, not unconditional. A popup!htmlvalue renders as raw markup only under a trusted capability policy; otherwise it is escaped and shown as text.<ml-map>is untrusted by default, so there!htmlcontent is escaped. In Astro,loadYAMLandloadFromGlobnow parse with core’s own options, so an!htmltag reaches the map as the same{ $html }value core produces (before, the Astro loader silently turned it into a plain string); it then renders under the same trust rule.- Malformed inline GeoJSON now warns. A v1 document whose inline GeoJSON
datais malformed gets a warning, whichmlym validate --strictand CI runs treat as an error. Check inline geometry before upgrading. - Format v2
style.metadatacarries through. In a v2 document,style.metadatais copied to the rootmetadataof the emittedstyle.json.
Astro with core 0.6.0 or earlier
Section titled “Astro with core 0.6.0 or earlier”With @maplibre-yaml/core 0.6.0 or earlier, every @maplibre-yaml/astro
component fails under astro dev with Failed to create map: Map is not a
constructor, while astro build works: Vite never pre-bundles maplibre-gl
when only a dependency’s .astro file imports it. Current releases are not
affected; upgrade core and the Astro package together
(How to upgrade). If a project must stay on core 0.6.0,
tell Vite to pre-bundle maplibre-gl:
import { defineConfig } from "astro/config";
export default defineConfig({ vite: { optimizeDeps: { include: ["maplibre-gl"] } },});