Choosing an engine¶
roadstyle can draw the same styled network four ways. They share the styling compiler (palettes, widths, the casing+fill sandwich, data-driven colour) — what differs is who renders it and where it runs. This page is the decision guide.
The four engines¶
| Engine | What it is | One line |
|---|---|---|
web (default) |
a finished MapLibre vector map in one self-contained HTML file | the map as a product |
folium |
a Leaflet map via the folium ecosystem | the map inside a folium workflow |
lonboard |
a GPU/WebGL map (deck.gl) in the notebook | the map at big-data scale |
| roadstyle.js / spec | styled JSON (to_spec) + a small JS renderer for your own page |
the map inside your web app |
Feature matrix¶
web |
folium |
lonboard |
spec + roadstyle.js | |
|---|---|---|---|---|
| Per-zoom road widths (osm-carto curve) | ✅ | — (fixed px) | — (fixed px) | — (fixed px) |
| Two-way lanes, one-way arrows, street names | ✅ | — | — | — |
| Tunnel/bridge grade separation | ✅ | draw order only | — | draw order only |
| 3D view (tilted camera, extruded cased bridge decks) | ✅ | — | — | — |
| Hover / click-select / popup or side panel | ✅ | tooltip + pin | hover tooltip | select events |
Base-map switcher (incl. tile-less blank) |
✅ | thumbnail switcher | fixed | from the spec |
Client-side recolouring (color_options) |
✅ dropdown | — | — | ✅ setColorField |
| JavaScript API (setters, id-set queries, events) | ✅ window.rs* |
— | — | ✅ RoadStyleMap (smaller) |
| Overlays (your zones / POIs / lines) | ✅ | via folium | — | — |
| Offline single file (no server, no internet) | ✅ (blank = zero requests) |
✅ (tiles need net) | notebook only | ✅ page or served |
| Comfortable data size | ~10⁴ inline; ~10⁵ with tiles=True (embedded PMTiles) |
~10³–10⁴ | 10⁵–10⁶+ | like web |
| Legends for data-driven colour | ✅ | ✅ | ✅ | ✅ |
Pre-highlighted selected= edges |
— (click instead) | ✅ | — | — |
Rules of thumb¶
- Start with
web. It's the default for a reason: the full cartographic engine, interactive, one offline file, and scriptable afterwards (window.rs*+ theui/templates). If you don't have a specific reason below, this is the answer. - Use
foliumwhen the map must live inside an existing folium/Leaflet workflow — you're composing with folium plugins, or you want theselected=pre-highlight and the pin-tooltip behaviour. Accept fixed-pixel widths and no labels/arrows/3D. - Use
lonboardwhen the bottleneck is size: hundreds of thousands of edges explored interactively in a notebook. Accept simpler styling (colour + width per edge; no casing sandwich, labels, or selection UI). - Use
to_spec/ roadstyle.js when your web app owns the page: a server renders fresh JSON per request (FastAPI+to_spec), or a static page loads a saved spec, and your own Leaflet/MapLibre/React code draws it — roadstyle stays the single source of styling truth via the baked__rs_*properties. See Frontend integration and Embedding.
Two combinations worth knowing:
web+ custom UI beats spec for most dashboards — since the savedwebpage exposes the fullrs*JavaScript API (queries, filtering, recolouring, selection, camera), you can build a dashboard around it with plain HTML (seeui/dashboard) and skip writing a renderer entirely. Reach for the spec path only when the map must integrate into an existing JS app's own map component.lonboardfor exploration,webfor the deliverable — samerender_edgescall, differentbackend=; find the story at scale, then ship the styled subset.
The same call, four ways¶
import geopandas as gpd
import roadstyle as rs
edges = gpd.read_file("edges.gpkg")
rs.render_edges(edges) # web (default)
rs.render_edges(edges, backend="folium") # folium / Leaflet
rs.render_edges(edges, backend="lonboard") # GPU, big data
spec = rs.to_spec(edges, color_by="aadt", cmap="viridis") # JSON for your own frontend