sMap interoperability
sMap interoperability
sMap follows open map standards, so it works inside other map tools and their styles, data and layers work on an sMap map. This page lists the standards, what each tool can do in both directions, how this is achieved, common use cases and the limits. The calls themselves are described in the maps guide.
1. Standards
| Standard | sMap reads | sMap serves or writes | Maps guide |
|---|---|---|---|
| Style Specification v8 (styles, sources, layers, expressions) | addSource, addStyleLayer, setPaint, setLayout, setFilter |
The style of each scheme and of each saved custom style | 6, 7 |
| TileJSON 3 | addRasterLayer({ url }), addVectorTiles({ url }) |
/v1/raster/<style>.json |
9, 11 |
| Mapbox Vector Tiles | addVectorTiles |
The basemap tiles | 9 |
| PMTiles | addVectorTiles({ pmtiles }) |
— | 9 |
| GeoJSON (RFC 7946) and simplestyle | addData, sMap.formats.read |
toGeoJSON, /v1/convert |
8 |
| KML and KMZ | addData |
toKML |
8 |
| GPX | addData |
— | 8 |
| Encoded polylines, precision 5 and 6 | format: 'polyline', format: 'polyline6' |
— | 8 |
| WKT and WKB | addData |
— | 8 |
| CSV | addData (latitude and longitude columns) |
— | 8 |
| TopoJSON | addData |
— | 8 |
| OGC WMS 1.3 | addWmsLayer (1.1.1 too) |
— | 9 |
| OGC WMTS 1.0 | addWmtsLayer (KVP and REST) |
/v1/raster/wmts?SERVICE=WMTS&REQUEST=GetCapabilities |
9, 11 |
| XYZ raster tiles | addRasterLayer({ tiles }) |
/v1/raster/<style>/{z}/{x}/{y}.png |
9, 11 |
| ArcGIS REST tile and vector tile services | addArcGisLayer (MapServer, ImageServer, VectorTileServer) |
— | 9 |
Every format is read by every SDK on the device and by POST /v1/convert on the map service.
2. Tools in both directions
| Tool | sMap in the tool | The tool's layers and data on sMap |
|---|---|---|
| Leaflet | @superrouteca/smap-leaflet: smapLayer(), smapRasterLayer() (12, Leaflet) |
@superrouteca/smap-leaflet/compat: createLeafletCompat(smap) runs L.marker, L.polyline, L.geoJSON, L.tileLayer and others on an sMap map (12, Leaflet) |
| OpenLayers | @superrouteca/smap-openlayers: smapLayer(), smapRasterLayer() (12, OpenLayers) |
@superrouteca/smap-openlayers/on-smap: addOpenLayersLayer(), addOpenLayersLayers() for XYZ, TileWMS, WMTS, VectorTile and Vector sources (12, OpenLayers) |
| Mapbox GL JS | @superrouteca/smap-mapbox: SMapMapbox, switchBasemap() (12, Mapbox GL JS) |
@superrouteca/smap-mapbox/on-smap: loadMapboxStyle(), copyMapboxLayers(), addMapboxLayers() (12, Mapbox GL JS) |
| deck.gl | @superrouteca/smap-deckgl: createSMapDeck(), createVectorBasemapLayer(), createRasterBasemapLayer() (12, deck.gl) |
map.addDeckLayer(), or deckLayers(map) from @superrouteca/smap-deckgl (12, deck.gl) |
| kepler.gl | Recipe: keplerMapStyles() and keplerTransformRequest() from @superrouteca/smap-deckgl (12, kepler.gl) |
Recipe: data exported from kepler.gl (CSV, GeoJSON) with map.addData(); its deck.gl layers with map.addDeckLayer() (8) |
| ArcGIS Maps SDK for JavaScript | @superrouteca/smap-arcgis: createSMapBasemap() (vector, or raster: true) (12, ArcGIS) |
@superrouteca/smap-arcgis/services: addArcGisService() for MapServer, ImageServer, VectorTileServer and one FeatureServer or MapServer layer (12, ArcGIS) |
| CesiumJS | @superrouteca/smap-cesium: createBaseLayer() (XYZ, or WMTS with wmts: true), addSMapData() (12, CesiumJS) |
@superrouteca/smap-cesium: addCesiumData() for CZML, KML and GeoJSON, entitiesToGeoJSON() (12, CesiumJS) |
| QGIS | Recipe: an XYZ or WMTS connection to /v1/raster (12, QGIS) |
Recipe: layers exported from QGIS as GeoJSON, KML, GPX or CSV with map.addData(); layers published as WMS or WMTS with addWmsLayer() / addWmtsLayer() (8, 9) |
| Google Maps JavaScript API | Recipe: sMap's points, lines and areas with pointsLayers() / linesLayers() from @superrouteca/smap-deckgl in GoogleMapsOverlay; the basemap stays Google's (12, Google Maps) |
Recipe: Google My Maps and Google Earth files (KML, KMZ) and encoded polylines with map.addData(); Google Maps style JSON imported on the Map styles page (7, 8) |
The adapters are on the downloads page and on npm. The playground has a working example of each layer feature.
3. How compatibility is achieved
- Vector where the tool can draw it, raster otherwise. Leaflet, OpenLayers, Mapbox GL JS, deck.gl and ArcGIS
read sMap's vector tiles. Tools that cannot read them use raster tiles drawn from the same styles:
/v1/raster, its TileJSON and its WMTS capabilities (11). - Leaflet and OpenLayers embed a full sMap map. The adapter places an sMap map inside the tool's map, so sMap's pins, popups and Auto Zoom stay available there.
- Mapbox GL JS draws sMap's style itself. sMap's style is a Style Specification v8 document, so Mapbox GL JS draws it natively; sMap's own layers are drawn on an overlay.
- deck.gl is interleaved. deck.gl layers are drawn among the map's own layers, under the labels or roads when a slot says so.
- Access is the same in every adapter. Each adapter takes a map key or a token (with renewal) and reads from the nearest map node, moving to the next node when one fails (2, 3).
- One layer JSON.
map.toJSON()andmap.loadLayers(json)use one document read by every SDK and adapter, so a map built on the web opens the same in the Android, iOS, Flutter, React Native, macOS and Windows SDKs (10). - Formats are read the same on every platform. The JavaScript, Kotlin, Swift and Dart readers and
/v1/convertare checked against one shared set of sample files with the expected GeoJSON. - Saved custom styles have a style URL. Any tool that reads a Style Specification style or raster tiles reads a
custom style by its URL:
/v1/styles/custom/sms_…or/v1/raster/custom:sms_…/{z}/{x}/{y}.png(7).
4. Use cases
Each use case is worked through, with complete code and a link to the running example, in sMap interoperability cases.
4.1 A Leaflet app moves its basemap to sMap
The app keeps its Leaflet map and adds sMap as its base layer. Its existing markers, polylines and GeoJSON layers are not changed.
smapLayer({ apiKey, style }).addTo(map)in place of the previous tile layer.- Or, to run the app on an sMap map:
createLeafletCompat(smap)and the app's existingL.*calls.
4.2 A Mapbox GL JS app moves to sMap's basemap
The app keeps its Mapbox GL JS map and its own sources and layers; only the basemap changes.
switchBasemap(mapboxgl, map, { access, style: 'light' }).- Create the map with
transformRequest: smapTransformRequest(access)when it uses tokens.
4.3 deck.gl or kepler.gl analytics over sMap
Heat maps, hexagons and arcs are drawn over an sMap basemap, under the labels.
- deck.gl:
createSMapDeck({ apiKey, style: 'dark', layers }), ormap.addDeckLayer(layer, { slot: 'labels' }). - kepler.gl:
keplerMapStyles({ apiKey, styles })asmapStylesandkeplerTransformRequest(access).
4.4 ArcGIS services and ArcGIS apps
An organisation's ArcGIS services are shown on an sMap map, or an ArcGIS app uses sMap as its basemap.
- On sMap:
addArcGisService(map, id, '…/MapServer')oraddArcGisService(map, id, '…/FeatureServer/0', { token }). - In ArcGIS:
map.basemap = await createSMapBasemap({ apiKey, style }).
4.5 CesiumJS globe imagery from sMap
A Cesium viewer uses sMap's raster tiles as the globe's imagery, without a Cesium ion account for it.
new Viewer('globe', { baseLayer: createBaseLayer({ apiKey, style }) }).addSMapData()for sMap's points, lines and areas in the viewer.
4.6 Planners use sMap in QGIS
Planners open sMap as a basemap in QGIS beside their own layers.
- An XYZ connection to
/v1/raster/<style>/{z}/{x}/{y}.png?token=sm1.…, or a WMTS connection to/v1/raster/wmts?SERVICE=WMTS&REQUEST=GetCapabilities&token=sm1.…. - A new token is issued by your server when the previous one expires.
4.7 Government and weather WMS overlays
A weather radar or a government flood map is drawn over the basemap, under the street names.
map.addWmsLayer('radar', { url, layers, slot: 'labels', opacity: 0.6 }).await map.addWmtsLayer(id, { url: '…/WMTSCapabilities.xml', layer })for a WMTS service.
4.8 KML from Google My Maps and GPX tracks from drivers
A customer's My Maps export and drivers' GPX tracks are shown on the map and exported again.
await map.addData('customer', kmzFile)andawait map.addData('tracks', gpxFile).map.toKML('customer')ormap.toGeoJSON('tracks')to export;POST /v1/convertfor files up to 20 MB.
4.9 A brand style from a Google Maps style JSON
A style shared on Snazzy Maps, or one already used on Google Maps, becomes an sMap custom style for the website and the apps.
- Import the JSON on the Map styles page (
/open-api/map-styles); entries without a counterpart are listed. style: 'custom:sms_…'in every SDK; the style URL in other tools.
4.10 The same layers on web, Android, iOS, Flutter and desktop
Layers built once on the web are loaded in the apps.
- On the web:
const saved = map.toJSON(), stored by your server. - In each app:
loadLayers(saved). A layer a platform cannot draw is skipped and the rest are loaded.
5. Limits
Leaflet and OpenLayers
| Topic | Limit |
|---|---|
| Drawing | The basemap is an embedded second map. Leaflet is flat; OpenLayers rotates but does not tilt. Neither shows 3D buildings. |
| WebGL | Without WebGL 2 the adapters use raster tiles. |
| Leaflet-compatible calls | L.divIcon is drawn as the default pin. A layer added again after a style change is drawn on top. |
| OpenLayers on sMap | OpenLayers style functions are not converted; vector tiles are drawn by the Style Specification layers you give. |
Mapbox GL JS
| Topic | Limit |
|---|---|
| sMap's own layers | Pins, popups, Auto Zoom, data files, WMS / WMTS / ArcGIS layers and deck.gl layers are drawn on an overlay above the Mapbox labels. |
| Projection | The map is kept in Web Mercator. |
| An existing map | It can be attached with a map key. Tokens work only when the map was created with smapTransformRequest(). |
| Icons | Mapbox sprite icons are not loaded. |
| Mapbox styles on sMap | mapbox:// and api.mapbox.com sources, the layers that read them, and background, sky and fog layers are left out and listed. |
deck.gl and kepler.gl
| Topic | Limit |
|---|---|
| Vector basemap drawn by deck.gl | No sprite icons, no labels placed along lines, no label collision. |
| sMap layers as deck.gl layers | Clustering, Auto Zoom, count badges, arrows and dashes are not drawn. |
| Platforms | Web only: not in the native SDKs, and not in the macOS and Windows SDKs. |
ArcGIS Maps SDK for JavaScript
| Topic | Limit |
|---|---|
| 3D | 3D buildings are drawn flat. |
| Vector basemap | sMap's style is converted into what ArcGIS's vector tile layer draws: labels in one font; for a name in another script, the local name on a second line; the first label position where sMap allows several; Han characters in their Simplified Chinese forms in every label language. basemap.smap.simplified lists each simplification. |
| Access | Tile requests made in ArcGIS workers may skip request interceptors. Use a map key rather than a token. |
| Feature layers on sMap | The layer's attribution is returned to the caller and is not drawn. |
| Vector tile services with their own fonts and icons | Labels are shown only for fonts that sMap serves; the service's icons are not loaded. This applies in every SDK. |
CesiumJS
| Topic | Limit |
|---|---|
| sMap in Cesium | Imagery only (raster tiles). No 3D buildings and no 3D Tiles. |
| Cesium data on sMap | 3D models, volumes and positions given by reference are skipped and listed. A time-dynamic position shows its first sample. 3D Tiles tilesets are refused. |
QGIS and other desktop programs
| Topic | Limit |
|---|---|
| Access | Desktop programs send no origin, so a map key alone is refused. Put a token in the URL (valid up to 24 hours), or set a Referer that is on the key's allowlist. |
WMTS
| Topic | Limit |
|---|---|
| Services read by sMap | Only Web Mercator tile matrix sets whose matrix ids are the zoom number. |
| In a browser | Reading a capabilities document needs the service to allow cross-origin requests. |
| sMap's own WMTS | It lists the five schemes only. Custom styles use the raster URL template. |
Google and Bing
| Topic | Limit |
|---|---|
| Tiles | Google and Bing tiles are never offered; their licences do not allow it. |
Formats
| Topic | Limit |
|---|---|
| Geometry | Rings are not closed and coordinates are not rounded. |
| CSV | A decimal comma is read only in files delimited by ; or a tab. Rows without a readable coordinate are skipped. |
| Size | /v1/convert takes up to 20 MB. A KMZ unpacks to at most 100 MB. |
Native SDKs
| Platform | Limit |
|---|---|
| iOS, Flutter | addData draws no popup; taps are still reported. |
| Flutter | A style's own fonts and icons cannot be added. |
| Android, iOS, Flutter, React Native | Video sources are not supported. |
| Android | GeoJSON clusterProperties are not passed. |
| iOS | 3D buildings under a custom style use the light colour. |
| Windows, macOS | The web SDK runs in the system web view, without deck.gl. |
| Windows | ConvertAsync needs the format. |
Raster tiles, style import and basemap options
| Topic | Limit |
|---|---|
| Raster tiles | No credit is drawn on the tiles. The credit is in TileJSON and WMTS and is shown by the SDKs and adapters. |
| Google style import | Entries without a counterpart are skipped and listed: partial feature types (for example poi.business), labels.icon, simplified, weight and invert_lightness. hue, saturation, lightness and gamma apply only to a colour in the same rule. |
| Basemap options | Label density is not offered. |
6. Attribution
The map data is © OpenStreetMap contributors. The OpenStreetMap credit and the sMap badge stay visible in every tool; the adapters add them to the tool's own attribution (13).