Skip to main content

Massif with MapLibre

Each variant is a standalone style JSON. Point the map at it:

const map = new maplibregl.Map({
container: 'map',
style: 'https://massif-maps.github.io/MassifMaps/styles/massif/outdoor.json',
center: [5.76, 45.31],
zoom: 12,
});
URLWhat
…/styles/massif/<variant>.jsonthe latest release
…/styles/massif/v<version>/<variant>.jsonone release, never changes — pin this in an app
…/styles/massif/versions.jsonevery published version

<variant> is streets, outdoor, topo, hybrid or eink. The same files are in the npm package (@massif-maps/styles/maplibre/) and in the massif-maplibre-<version>.zip release asset; their sprite URL points at the website, so they work as they are or copied to your own host (rewrite sprite to serve that too).

The styles read OpenFreeMap's OpenMapTiles planet and fonts, and Mapterhorn's DEM for the relief. They work in Mapbox GL JS too, which reads the same style spec.

Every variant carries the relief (hillshade) and the contours (contour, contour-index, contour-label); outdoor and topo show them, the others ship them with visibility: none:

for (const id of ['hillshade', 'contour', 'contour-index', 'contour-label']) {
map.setLayoutProperty(id, 'visibility', 'visible');
}

The SDK's style parameters (poiStyle, track_min_zoom, building_opacity...) are baked into the MapLibre styles at each variant's default: MapLibre has no parameter mechanism. To change one, edit the style JSON or build your own.

The optional sources​

Four sources have no public host. The published styles keep their layers, and the source itself is an empty placeholder of the same name — GeoJSON with no features, or a transparent raster for satellite — so the style validates and those layers draw nothing until you put the real source back. metadata["massif:placeholder-sources"] in each style lists them.

SourceLayers it feedsVariantsTiles it expects
bathymaplow-zoom landcover under z8, ocean depthallvector, z0-6: layer global_landcover (class: built, glacier, swamp, marsh, tree, crop, scrub, heath, grass, sand), layer depth (min_depth in metres, 0 = the whole ocean)
contourscontour lines and labelsall (shown in outdoor, topo)vector, z11-14: layer contour, ele (m), div (100 = index line)
routeswaymarked route bandsoutdoor, topovector: layer route, class hiking / bicycle, network 1-4 (1-2 = international / national)
satellitethe imagery under the roadshybridraster XYZ

Replace a placeholder before the map reads the style:

const style = await (await fetch('https://massif-maps.github.io/MassifMaps/styles/massif/outdoor.json')).json();
style.sources.contours = { type: 'vector', url: 'https://tiles.example.com/contours.json' };
style.sources.bathymap = { type: 'vector', url: 'https://tiles.example.com/bathymap.json' };
const map = new maplibregl.Map({ container: 'map', style });

or keep loading it by URL and swap it in transformStyle:

map.setStyle(url, {
transformStyle: (previous, next) => ({
...next,
sources: { ...next.sources, satellite: { type: 'raster', tiles: ['https://imagery.example.com/{z}/{x}/{y}.jpg'], tileSize: 256 } },
}),
});

The bathymetry archive is Alpimaps' (scripts/make_bathymap.py: ESA WorldCover classes and Natural Earth isobaths). A source whose maxzoom is 6 is overzoomed to z8 by MapLibre, which is where the style hands over to OpenMapTiles' own landcover.

Night, lights and 3D​

The styles carry the SDK's day-cycle colours in metadata only; MapLibre draws the day. 3D buildings are fill-extrusion layers and draw in MapLibre as they are.