Quick start: MapLibre GL JS
This example opens the Updraft "pilot eye" vector style and filters the thermal grid by month, time of day and wind direction. The same code runs on this site: live example.
1. Install
npm install @updraft/maps [email protected]
A container for the map:
<div id="map" style="height: 70vh"></div>
<script type="module" src="./main.js"></script>
2. Map and thermal filter
Copy this file into your project (updraft-map.js). The Updraft client package @updraft/maps does most of the work: updraftMapOptions opens the style, adds the X-Api-Key header (when you have a key) to requests for the Updraft tile server only and keeps the attribution box open; setThermalFilter points the thermal source at the filtered address. The package does not import maplibre-gl itself; it works with your copy. The package's API client and types: Authentication.
// Updraft quick start 1: MapLibre GL JS + the Updraft "pilot eye" vector style + the thermal grid.
// npm install @updraft/maps [email protected]
import { Map as MapLibreMap, NavigationControl, ScaleControl } from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import { updraftMapOptions } from '@updraft/maps/maplibre';
// setThermalFilter(map, { month, hourBucket, windSector }) points the style's `thermals` source at
// a breakdown; thermalsUrl(filter) gives its TileJSON address.
export { setThermalFilter } from '@updraft/maps/maplibre';
export { thermalsUrl } from '@updraft/maps';
/**
* Creates the map. `apiKey` is optional: with a key (scope `tiles`) every request to the Updraft
* tile server, and only to it, carries the `X-Api-Key` header and counts towards your key's usage;
* without one the public tile path is used, which is limited per client address.
* `updraftMapOptions` also keeps the attribution box open ("© Updraft · © OpenStreetMap
* contributors · © OpenMapTiles · Copernicus DEM" must stay visible).
* @param {object} options
* @param {HTMLElement | string} options.container
* @param {string} [options.apiKey] key with the `tiles` scope (header, never in the URL)
* @param {'light' | 'dark'} [options.theme] published style; default light
* @param {string} [options.style] your own style URL instead
* @param {string} [options.tilesUrl] Updraft tile server root; default https://maps.updraftmaps.com
* @param {[number, number]} [options.center] [longitude, latitude]
* @param {number} [options.zoom]
* @returns {MapLibreMap}
*/
export function createUpdraftMap(options) {
const map = new MapLibreMap(updraftMapOptions(options));
map.addControl(new NavigationControl(), 'top-right');
map.addControl(new ScaleControl({ unit: 'metric' }), 'bottom-left');
return map;
}
// Usage:
// const map = createUpdraftMap({ container: 'map', apiKey: 'upd_…' });
// map.on('load', () => setThermalFilter(map, { month: 7, hourBucket: 6, windSector: 6 }));
Usage (main.js):
import { setWorkerUrl } from 'maplibre-gl';
import workerUrl from 'maplibre-gl/dist/maplibre-gl-worker.mjs?url';
import { createUpdraftMap, setThermalFilter } from './updraft-map.js';
// MapLibre 6 loads its worker from a separate file; with a bundler give its address (Vite):
setWorkerUrl(workerUrl);
const map = createUpdraftMap({ container: 'map', apiKey: 'upd_…' }); // the key is optional
map.on('load', () => {
// July, 12:00–14:00 local time, wind from the west
setThermalFilter(map, { month: 7, hourBucket: 6, windSector: 6 });
});
3. Thermal parameters
The thermal grid is Martin's thermals function source; the filter is the query string of the TileJSON address (https://maps.updraftmaps.com/thermals?month=7&hour_bucket=6).
| Parameter | Values | "All" | Meaning |
|---|---|---|---|
month |
1–12 | 0 (default) | Local month |
hour_bucket |
0–11 | 12 (default) | Local two-hour slot: 0 = 00–02, 6 = 12–14 |
wind_sector |
0–7 | 8 (default) | 45° sector the 850 hPa wind blows from: 0 north, 2 east, 4 south, 6 west |
An invalid value returns an empty tile. The grid is drawn at z8–14 (z8–10 ~5 km², z11–14 ~0.1 km² hexagons); every cell has avg_climb_ms (mean climb, 0.1 m/s), confidence_tier (low, medium, high) and min_pilots (at least N pilots). Cells without enough distinct pilots never arrive (Privacy). Details: Tiles and styles.
4. Key and origin
transformRequestadds the key only to requests for the Updraft tile server; it is never written into the URL (?key=), so it stays out of server and CDN logs.- A key that goes to the browser can be read by anyone: use a key with the
tilesscope only. If it leaks, only tiles can be read and the key is revoked (Authentication). - The tile server accepts browser requests from registered origins only (CORS). Tell us your site's origin (
https://example.com) when you ask for the key; for local trials also an address such ashttp://localhost:5173. - Requests without a key work too, but they are limited per client address and are not counted for you.
5. Attribution
The style carries its attribution line: "© Updraft · © OpenStreetMap contributors · © OpenMapTiles · Copernicus DEM". The example keeps MapLibre's attribution box expanded; do not hide the line or put it only in a menu. If you use the thermal layer, also put the DWD wind data notice on your licences page (Attribution rules).