E2 with MapLibre GL

MapLibre GL renders E2 results as styled vector layers: search becomes a GeoJSON source, routes draw as line layers, and compute drives paint properties.

Documentation navigation

How E2 fits

E2 queries return GeoJSON FeatureCollections, which map directly to MapLibre geojson sources. Add a circle layer for search results, a line layer for routes, and update paint properties from compute results.

Setup

terminal
npm install maplibre-gl @embed-earth/sdk-test
map.ts
import maplibregl from "maplibre-gl";

const map = new maplibregl.Map({
  container: "map",
  style: "https://demotiles.maplibre.org/style.json",
  center: [-73.99, 40.74],
  zoom: 12,
});

Tiles

tiles.ts
map.addSource("planet", {
  type: "vector",
  tiles: ["https://tiles.embed.earth/planet/{z}/{x}/{y}.pbf"],
});

map.addSource("restaurants", {
  type: "vector",
  tiles: ["https://tiles.embed.earth/restaurant/{z}/{x}/{y}.pbf"],
});
Feature tile URLs resolve the newest published PMTiles snapshot. See the Tiles guide for source-layer and styling details.

Search

search.ts
const e2 = new E2();
const places = await e2.search({
  feature: "restaurant",
  area: "Manhattan",
  mode: "auto",
  limit: 1000,
});

map.addSource("restaurants", {
  type: "geojson",
  data: places,
});

map.addLayer({
  id: "restaurants",
  type: "circle",
  source: "restaurants",
  paint: { "circle-radius": 4, "circle-color": "#e2b07a" },
});

Routing

routing.ts
const route = await e2.route.route({
  locations: [
    { lat: 40.74, lon: -73.99 },
    { lat: 40.71, lon: -74.01 },
  ],
  mode: "walking",
});

map.addSource("route", {
  type: "geojson",
  data: {
    type: "Feature",
    properties: {},
    geometry: route.geometry,
  },
});

map.addLayer({
  id: "route",
  type: "line",
  source: "route",
  layout: { "line-join": "round", "line-cap": "round" },
  paint: { "line-width": 4, "line-color": "#e2b07a" },
});

Compute

compute.ts
const density = await e2.compute.feature("restaurant")
  .region("Manhattan")
  .near("park", 500)
  .density();

// Scale marker size with the computed density
const radius = Math.max(3, Math.min(10, Math.round(density / 2)));
map.setPaintProperty("restaurants", "circle-radius", radius);

new maplibregl.Popup({ closeButton: false })
  .setLngLat([-73.99, 40.74])
  .setHTML(`<strong>${density.toFixed(1)}</strong> restaurants/km&sup2; near parks`)
  .addTo(map);

Notes

Run queries after the map load event so sources and layers attach to a ready style. Call map.getSource(...).setData(...) instead of re-adding a source when results refresh.