All integrations MapLibre Leaflet OpenLayers React WordPress API docs

ExpressMaps in Leaflet

Keep your Leaflet code, markers and plugins, and swap the tile layer for sharp OpenStreetMap vector maps. The map below is live Leaflet: try the style picker in the top-right corner.

How it works

Leaflet draws raster image tiles out of the box. ExpressMaps serves vector tiles, which stay crisp on high-density screens and at every zoom level, so you render them inside Leaflet with the official maplibre-gl-leaflet plugin. It adds one Leaflet layer backed by MapLibre GL JS. Everything else, from markers and popups to GeoJSON and third-party Leaflet plugins, keeps working as before.

1. Include Leaflet, MapLibre and the plugin

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css">
<script src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script>
<script src="https://unpkg.com/@maplibre/maplibre-gl-leaflet@0.0.22/leaflet-maplibre-gl.js"></script>

2. Add the ExpressMaps layer

Where you would normally call L.tileLayer(...), call L.maplibreGL with a style URL instead. Replace YOUR_API_KEY with a key from the console.

<div id="map" style="width: 100%; height: 400px;"></div>
<script>
  var map = L.map("map").setView([51.5072, -0.1276], 12);

  L.maplibreGL({
    style: "https://tiles.expressmaps.com/styles/standard.json?key=YOUR_API_KEY"
  }).addTo(map);
</script>

Markers, popups and GeoJSON

These are ordinary Leaflet layers drawn on top of the map, so existing code needs no changes. Leaflet uses [lat, lng] order.

L.marker([51.5072, -0.1276])
  .bindPopup("<b>Our office</b><br>Open 9 to 5")
  .addTo(map);

fetch("/stores.geojson")
  .then(function (r) { return r.json(); })
  .then(function (data) {
    L.geoJSON(data, {
      onEachFeature: function (f, layer) { layer.bindPopup(f.properties.name); }
    }).addTo(map);
  });

Let visitors switch styles

Create one layer per style and hand them to Leaflet's layers control. This is what the live map above does. See all ten styles.

var key = "YOUR_API_KEY";
function expressmaps(style) {
  return L.maplibreGL({ style: "https://tiles.expressmaps.com/styles/" + style + ".json?key=" + key });
}
var styles = {
  "Standard": expressmaps("standard"),
  "Subtle": expressmaps("subtle"),
  "Darklands": expressmaps("darklands")
};
styles["Standard"].addTo(map);
L.control.layers(styles).addTo(map);

With npm and a bundler

npm install leaflet maplibre-gl @maplibre/maplibre-gl-leaflet
import L from "leaflet";
import "leaflet/dist/leaflet.css";
import "maplibre-gl/dist/maplibre-gl.css";
import "@maplibre/maplibre-gl-leaflet";

const map = L.map("map").setView([51.5072, -0.1276], 12);
L.maplibreGL({ style: "https://tiles.expressmaps.com/styles/standard.json?key=YOUR_API_KEY" }).addTo(map);

Moving from a raster tile URL

If your map uses L.tileLayer("https://.../{z}/{x}/{y}.png") today, remove that line and add the L.maplibreGL layer above. We do not serve raster PNG tiles; vector tiles are smaller to download, sharp on retina screens and rotate labels correctly. Attribution comes from the style, so you can drop any hand-written OpenStreetMap credit.

Things to know

  • The plugin adds MapLibre GL JS (about 210 KB gzipped) to your page. For a new project with no Leaflet code to keep, use MapLibre GL JS directly: it is one library instead of two and supports rotation and tilt.
  • A map load is counted when the style is requested. Panning and zooming are free, however long the visitor stays.
  • Restrict your key to your domains in the console. The key is visible in page source, which is normal for web maps; the domain restriction is what protects it.
  • Keep the attribution control on. The OpenStreetMap credit is required by the data licence.
  • Leaflet plugins that draw on their own canvas or SVG layer (clustering, heatmaps, drawing tools) work unchanged on top of the vector layer.

Get a free API key Leaflet in the docs