How to Integrate External Data Sources with GeoLibre: Overture Maps, Planetary Computer, and Earth Engine
Integrate any external raster service into GeoLibre by implementing the TimelapseProvider interface, which converts remote tile URLs into map layers through the Zustand store and MapLibre sync layer.
GeoLibre is architected as a plugin‑driven, store‑driven application where all map data flows through GeoLibreLayer records in the central Zustand store. This design makes it straightforward to bring in external imagery from sources like Google Earth Engine, Microsoft Planetary Computer, or Overture Maps. The integration pattern is consistent across providers: generate tile‑URL templates, wrap them in TimelapseFrame objects, and register a provider that the Timelapse control consumes automatically.
Understanding the Layer Architecture
Every raster or vector layer that appears on the map originates as a GeoLibreLayer in the store. The packages/map/src/MapController.ts file handles synchronizing these store records to actual MapLibre sources through its syncLayers method. For external raster services, you don't manipulate the store directly—instead, you implement a provider that generates frame objects containing tile URL templates.
The TimelapseProvider interface in packages/plugins/src/plugins/timelapse-providers.ts defines the contract:
id– unique provider identifiername– human‑readable label shown in the UI pickerattribution– credit string rendered on the maplistFrames()– async method returningTimelapseFrame[]with tile URLs, zoom limits, and metadata
When a user selects a frame, the Timelapse control instantiates a raster source using the tileUrlTemplate and adds it to the map through the standard store → MapController → MapLibre pipeline.
Integrating Google Earth Engine
Earth Engine exposes raster data through getMapId() (or getTileUrl()), which returns a tile template string containing {z}/{x}/{y} placeholders. Your provider wraps these templates into frames.
import { TimelapseProvider, TimelapseFrame } from "./timelapse-providers";
import { registerTimelapseProvider } from "./timelapse-providers";
/** Fetches a tile URL template for a specific year from EE. */
async function eeTileUrl(year: number): Promise<string> {
const collection = ee.ImageCollection("MODIS/061/MOD13A2")
.filter(ee.Filter.calendarRange(year, year, "year"));
const image = collection.first();
const { tileUrl } = image.getMap({ format: "png" });
// Returns: "https://earthengine.googleapis.com/map/{mapid}/{z}/{x}/{y}?token=..."
return tileUrl;
}
const earthEngineProvider: TimelapseProvider = {
id: "ee-modis-ndvi",
name: "Google Earth Engine NDVI",
attribution: "© Google Earth Engine",
async listFrames() {
const years = [2018, 2019, 2020, 2021];
const frames: TimelapseFrame[] = await Promise.all(
years.map(async (y) => ({
id: `ee-modis-${y}`,
label: `${y}`,
year: y,
tileUrlTemplate: await eeTileUrl(y),
attribution: `NDVI ${y} via Google Earth Engine`,
minzoom: 0,
maxzoom: 12,
}))
);
return frames;
},
};
registerTimelapseProvider(earthEngineProvider);
The earth-engine-auth.ts file in the same directory handles OAuth authentication and reports availability to the UI, so your provider can assume an authenticated EE client is present when registered.
Integrating Microsoft Planetary Computer
Planetary Computer serves imagery through its STAC API. You query for collections, extract asset URLs, and construct tile templates. The signed URLs returned by Planetary Computer typically include the {z}/{x}/{y} structure directly.
import { TimelapseProvider, TimelapseFrame } from "./timelapse-providers";
import { registerTimelapseProvider } from "./timelapse-providers";
const PC_SEARCH_URL = "https://planetarycomputer.microsoft.com/api/stac/v1/search";
async function fetchPcMosaic(year: number): Promise<string> {
const body = {
collections: ["sentinel-2-l2a"],
datetime: `${year}-01-01/${year}-12-31`,
limit: 1,
query: { "eo:cloud_cover": { lt: 0.1 } },
};
const resp = await fetch(PC_SEARCH_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
const json = await resp.json();
const asset = json.features[0].assets["visual"];
// Signed href contains z/x/y placeholders ready for MapLibre
return asset.href;
}
const planetaryComputerProvider: TimelapseProvider = {
id: "pc-sentinel2",
name: "Planetary Computer Sentinel-2",
attribution: "© Microsoft Planetary Computer",
async listFrames() {
const years = [2020, 2021, 2022];
const frames: TimelapseFrame[] = await Promise.all(
years.map(async (y) => ({
id: `pc-s2-${y}`,
label: `${y}`,
year: y,
tileUrlTemplate: await fetchPcMosaic(y),
attribution: `Sentinel-2 ${y} via Planetary Computer`,
minzoom: 0,
maxzoom: 14,
}))
);
return frames;
},
};
registerTimelapseProvider(planetaryComputerProvider);
Because Planetary Computer returns signed URLs with embedded tokens, each frame carries a complete, authenticated tile template that requires no additional request headers.
Integrating Overture Maps and Other Tile Sources
Overture Maps distributes vector tiles through AWS S3 or CDN endpoints. For raster‑style integration, you can:
- Create a vector tile provider – Implement a variant of
TimelapseProviderthat returnsvectortype sources instead of raster, pointing to Overture's{z}/{x}/{y}.pbfendpoints - Use a raster proxy – Pre‑render Overture data into raster tiles, then follow the standard provider pattern above
The source-coop-api.ts file demonstrates how to structure catalog‑based providers that query external APIs before generating frames. Adapt this pattern for Overture's partition‑based data layout:
- Query Overture's release manifest for available themes (buildings, places, transportation)
- Generate one
TimelapseFrameper theme or version - Point
tileUrlTemplateto the appropriate tile endpoint (e.g.,https://overturemaps-tiles.s3.amazonaws.com/2024-04-16/buildings/{z}/{x}/{y}.pbf)
Registering and Activating Your Provider
The provider lifecycle follows three stages:
- Import and register – Your provider file imports
registerTimelapseProviderfromtimelapse-providers.tsand calls it at module initialization - UI discovery –
TimelapseControl.tsxreads thetimelapseProvidersregistry and populates the provider picker dropdown - Frame activation – On user selection,
listFrames()executes, and the returned frames populate the year slider. Selecting a frame triggersMapController.ts→syncLayersto create the MapLibre raster source
Ensure your provider module is imported early—typically in packages/plugins/src/index.ts or equivalent—to guarantee registration before the Timelapse UI mounts.
Handling Custom Formats and Size Limits
Remote data integration must respect GeoLibre's format classification system. The remote-file-formats.ts file centralizes:
- Format detection – Mapping file extensions to processing strategies
- Size limits – Enforcing DuckDB and memory constraints for downloaded data
If your external source uses a non‑standard extension or URL pattern, extend the RemoteFileFormat union type and add detection logic in remote-file-formats.ts. This ensures consistent behavior for size‑checking and streaming limits across all remote sources.
Summary
- Implement
TimelapseProvider– Defineid,name,attribution, andlistFrames()to generate tile‑URL templates for any external service - Wrap Earth Engine – Use
getMap()orgetTileUrl()to obtain authenticated tile templates, then return them asTimelapseFrameobjects - Query Planetary Computer – Hit the STAC API, extract signed asset URLs, and convert to frames with appropriate zoom limits
- Register early – Call
registerTimelapseProvider()at module load soTimelapseControl.tsxdiscovers your source - Extend formats if needed – Add new URL patterns to
remote-file-formats.tsto maintain consistent size and streaming behavior
Frequently Asked Questions
What file should I modify to add a new external data provider?
Create a new TypeScript file in packages/plugins/src/plugins/ that implements TimelapseProvider, then import and register it in the package index. The timelapse-providers.ts file defines the interface and registry, while source-coop-api.ts provides a working template for API‑based providers.
Does GeoLibre support vector tiles from Overture Maps?
Yes. The provider pattern accepts any MapLibre‑compatible source. For vector tiles, return a TimelapseFrame with a URL template pointing to .pbf endpoints and ensure your consuming code sets the source type to vector. You may need to extend MapController.ts logic if you require custom layer styling beyond the default raster handling.
How does authentication work for Earth Engine?
The earth-engine-auth.ts plugin manages OAuth flow and exposes an authenticated ee client globally. Your provider can assume this client is initialized when listFrames() is called. For production deployments, ensure the token refresh logic in earth-engine-auth.ts remains active throughout the session.
Can I combine multiple external sources in one provider?
Yes. A single TimelapseProvider can return frames from heterogeneous sources—mix Earth Engine, Planetary Computer, and custom endpoints. Each TimelapseFrame carries its own tileUrlTemplate and attribution, so the map renders them uniformly through the same syncLayers pipeline.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →