SWMAPS DocumentationAPI portal

Build a map

Styles and overlays

Customize the camera and map layers while keeping resource URLs, attribution and release versions consistent.

On this page

Camera, markers and popups #

Prerequisites: a map created using the web guide and a successful load. MapLibre coordinates are longitude first.

javascript
import { maplibregl } from 'https://maps.example/sw-map.js';
// Use the map returned by createMap().
map.flyTo({ center: [123.8985, 10.3326], zoom: 14 });
const popup = new maplibregl.Popup().setText('Station Lahug');
const marker = new maplibregl.Marker().setLngLat([123.8985, 10.3326])
  .setPopup(popup).addTo(map);
// When removing this feature: marker.remove();

The shared map already adds navigation and scale controls. Supply MapLibre constructor options through mapOptions for initial center, zoom, pitch, bearing, bounds and other renderer settings. Use text content for untrusted popup labels.

GeoJSON overlays and style changes #

javascript
import { setStyle } from 'https://maps.example/sw-map.js';
const stations = { type: 'FeatureCollection', features: [
  { type: 'Feature', properties: { name: 'Station' },
    geometry: { type: 'Point', coordinates: [123.8985, 10.3326] } }
] };
function addStations() {
  if (map.getSource('stations')) return;
  map.addSource('stations', { type: 'geojson', data: stations });
  map.addLayer({ id: 'stations', type: 'circle', source: 'stations',
    paint: { 'circle-radius': 7, 'circle-color': '#087c64',
      'circle-stroke-width': 2, 'circle-stroke-color': '#ffffff' } });
}
map.on('style.load', addStations);
if (map.isStyleLoaded()) addStations();
// User chooses a theme:
setStyle(map, 'dark');

Expected result: your stations appear in either theme. A style change replaces its sources and layers, so re-add your overlays after style.load. Update data through map.getSource(id).setData(geojson). The shared style helper preserves the bathymetry choice; the grid helper reinstalls its overlays. Keep your own route and sector data separately.

Current, pinned and raw styles #

URL or optionBehavior
/maps/styles/light.json or dark.jsonCurrent release, server-resolved URLs
/maps/v1/releases/<id>/files/styles/dark.jsonA retained named release
?key=YOUR_API_KEYAuthenticate and append the key to style resource URLs
?base=https%3A%2F%2Fapp.example%2FmapsUse the supplied map-data root for __MAP_BASE__
?raw=1Return the stored style with __MAP_BASE__ intact; authentication still applies

Style URLs name exact dated PMTiles files. Glyphs and sprites must remain reachable at the resolved root. Never replace PMTiles with a tile-template URL unless your app actually serves that protocol. resolveStyle fills source URLs, tile arrays, glyphs and sprite URLs in a clone of a raw style; it does not download files.

javascript
import { configure, mapsUrl } from '@sw-maps/core/config';
import { resolveStyle } from '@sw-maps/core/style';
configure({ baseUrl: 'https://maps.example/' });
const rawUrl = mapsUrl('maps/styles/dark.json?raw=1');
const response = await fetch(rawUrl, { headers: { 'X-API-Key': 'YOUR_API_KEY' } });
if (!response.ok) throw new Error('Style unavailable');
const style = resolveStyle(await response.json(), 'https://app.example/maps');
// app.example must proxy and authorize every referenced resource.

Attribution and limits #

Keep the style’s source attribution and the renderer’s attribution control visible, including in exported screenshots. The base attribution is © OpenStreetMap contributors · Protomaps · Natural Earth. Bathymetry needs its own dataset credits and the not-for-navigation notice. See Data and limitations.

Switching styles does not add new datasets to a release. Discover bathymetry through style metadata/release layers instead of assuming GMRT or another optional layer exists. A missing custom overlay after a style switch usually means its style-load handler was omitted.