Skip to content

Settings & palettes

The look of a map is a profile (widths, zooms, sizes) and a palette (colors), picked by name; the other settings are the base map, the camera and the API keys.

Settings levels

Each level overrides the ones above it. State only what changes; everything else keeps the bundled default.

level where scope
1. bundled data/defaults.json (in roadstyle-assets) the defaults
2. user $XDG_CONFIG_HOME/roadstyle/roadstyle.json (else ~/.config/roadstyle/roadstyle.json) read at import
3. project ./roadstyle.json in the working directory read at import
4. explicit file the path in $ROADSTYLE_CONFIG read at import
5. code rs.use_settings("my.json") or a dict (several allowed; none = drop them) rest of the process
6. one call rs.render_edges(edges, settings={...}) this render only

Files at levels 2-4 are read when roadstyle is imported: create them before import roadstyle. A file that cannot be read (not JSON or YAML, not a mapping) is an error that names the file. A settings file can be JSON or YAML (.yaml, .yml).

Profiles and palettes

The look of a map is two files, picked by name (docs/design/style_config.md). Python holds no style value.

holds bundled pick
palette only colors: road classes (fill, casing, opacity), names, arrows, bridges, tunnels, selection, data maps, overlays, boundary, background, access amber (default), carto, highsat, mono in roadstyle/data/palettes/ palette="carto"
profile everything that is not a color: widths by zoom, class order and minzoom, zoom ranges of names and arrows, sizes, dashes, caps, the tunnel look default, highsat in roadstyle/data/profiles/ profile="highsat"

Read the bundled files for every key and its comment. profile="highsat", palette="highsat" is the high-saturation look with its own widths and dashes; palette="highsat" alone uses the default profile.

Your own: a file ./palettes/<name>.yaml or ./profiles/<name>.yaml in the working directory (or under ~/.config/roadstyle/). It states only what it changes and merges over amber or default. Pick it by its name:

# ./palettes/night.yaml
classes:
  residential: {fill: "#334155"}
labels: {color: "#e2e8f0", halo_color: "#0f172a", halo_width: 1}    # halo_width is a size: it belongs to the profile
bridges: {casing_color: "#94a3b8"}
rs.render_edges(edges, palette="night")                 # this render
rs.render_edges(edges, profile="highsat", palette="highsat")
rs.use_settings({"palette": "night"})                   # the rest of the process

An unknown name is an error that lists the names there are. A palette is a file: Python has no palette registry.

The settings file

Every settings level uses one layout. profile and palette name the look; config holds what is not a look:

key holds merges
profile, palette names (the last level that gives one wins) replace
config basemap, camera, annotations (slot_m), tiles, api_key, api_keys per key
{
  "profile": "default",
  "palette": "carto",
  "config":  { "basemap": "ofm_positron" }
}

The older layout: a settings file can still give style values as palettes, selection, roads or as style keys of config (labels, arrows, bridge_*, tunnel_*, minzoom, ...). roadstyle reads each one as its profile or palette key and gives a DeprecationWarning that names the new key (config.bridge_casing_color -> theme bridges.casing_color). A palette entry can also be wrapped as {"roads": {...}}.

Palettes

Pick one with palette=. Widths are px at city zoom; the web backend scales them with zoom. All four palettes: opacity 1.0.

The amber colours: orange, yellow and green main roads, slate-grey streets; carto's widths and casings.

highway fill casing width / casing width dash
motorway #f28c28 #dc2a48 6.0 / 8.0
trunk #f5a623 #c84e2f 5.5 / 7.5
primary #f4c542 #a06b00 4.5 / 6.5
secondary #f7df72 #707d00 3.5 / 5.5
tertiary #b8d986 #bcbcbc 2.5 / 4.0
unclassified #ffffff #bcbcbc 2.0 / 3.5
residential #d7dee8 #bcbcbc 2.0 / 3.5
living_street #cbd5e1 #cccccc 1.8 / 3.0
service #94a3b8 #d4d4d4 1.2 / 2.2
track #a3a3a3 #9e7b54 1.5 4, 4
cycleway #5c7cb6 same 1.2 3, 3
footway #C59D9D same 1.2 4, 4
path #C59D9D same 1.2 2, 5

Bright fills, light-grey casing on major roads, no casing on minor ones.

highway fill casing width / casing width dash
motorway #00E5FF #bcbcbc 6.0 / 8.0
trunk #FF007F #bcbcbc 5.5 / 7.5
primary #FF9100 #bcbcbc 4.5 / 6.5
secondary #FFEA00 #bcbcbc 3.5 / 5.5
tertiary #00E676 #bcbcbc 2.5 / 4.5
unclassified, residential #FFFFFF #bcbcbc 2.0 / 4.0
living_street #DDDDDD none 2.0
pedestrian #DDDDDD none 1.5
service #F0F0F0 none 1.0
track #9E7B54 none 1.5
cycleway #2980B9 none 1.5 6, 4
footway, path #D98880 none 1.5 4, 4

The OpenStreetMap Carto look: muted fills, a darker casing per class.

highway fill casing width / casing width dash
motorway #e892a2 #dc2a48 6.0 / 8.0
trunk #f9b29c #c84e2f 5.5 / 7.5
primary #fcd6a4 #a06b00 4.5 / 6.5
secondary #f7fabf #707d00 3.5 / 5.5
tertiary #ffffff #bcbcbc 2.5 / 4.0
unclassified, residential #ffffff #bcbcbc 2.0 / 3.5
living_street #ededed #cccccc 1.8 / 3.0
service #ffffff #d4d4d4 1.2 / 2.2
track #9e7b54 same 1.5 4, 4
cycleway #5c7cb6 same 1.2 3, 3
footway #C59D9D same 1.2 4, 4
path #C59D9D same 1.2 2, 5

Greys only: a quiet base for data colours (palette="mono" + color_options).

highway fill casing width / casing width dash
motorway #707070 #3c3c3c 6.0 / 8.0
trunk #7a7a7a #444444 5.5 / 7.5
primary #8a8a8a #4f4f4f 4.5 / 6.5
secondary #9c9c9c #5c5c5c 3.5 / 5.5
tertiary #b0b0b0 #6e6e6e 2.5 / 4.0
unclassified, residential #c4c4c4 #828282 2.0 / 3.5
living_street #d4d4d4 #9a9a9a 1.8 / 3.0
service #e4e4e4 #bcbcbc 1.2 / 2.2
track #9a9a9a same 1.5 4, 4
cycleway #888888 same 1.2 3, 3
footway #ABABAB same 1.2 4, 4
path #ABABAB same 1.2 2, 5

In every palette:

  • *_link roads take the parent's colour and 0.6 × its width (profile roads.links.width).
  • Tunnels: the profile key tunnels.strength (default 60) moves everything on a tunnel toward the palette colour tunnels.toward (default Sand). The casing is dashes: one colour, or a two-colour pattern from tunnels.palette (design).
  • Bridges: the casing colour is bridges.casing_color (slate #64748b) and the casing is bridges.casing_extra (1.5 px) wider. The shadow is bridges.shadow in the profile and the palette.
  • An unknown class draws like unclassified.

Custom palettes

A palette is a YAML file. To add a class to a palette, add it under classes: in ./palettes/<name>.yaml, and pick the file with palette="<name>" (Profiles and palettes). The file states only what it changes. A class needs a fill, and it can have casing, dash ([on, off] px) and opacity (1.0). The widths are in the profile (roads.classes). For a non-OSM class column, give a palette and a profile keyed by your classes, and pass highway_col=.

# ./palettes/busway.yaml
classes:
  busway: {fill: "#FF00AA"}

Base maps & API keys

basemap= picks the base map; the default is ofm_positron (config.basemap). The seven base maps of roadstyle are in rs.BASEMAPS. None of them needs a key.

key base map dark twin
ofm_liberty OpenFreeMap Liberty (vector style) ofm_fiord
ofm_positron OpenFreeMap Positron (vector style) ofm_dark
osm OpenStreetMap none
esri_gray Esri Gray esri_dark_gray
esri_street Esri Streets none
satellite Esri Satellite (World Imagery) none
blank none: a plain canvas, no network requests, fully offline blank_dark

A dark twin comes into the list with its light map, and the page theme switches between the two.

Removed base maps

Earlier versions had more base maps. A page that asks for a key that no longer exists gets ofm_positron and a warning. rs.get_basemap gives an error for such a key. The CHANGELOG lists the removed keys.

Other sources:

  • A tile URL: basemap="https://tiles.example.com/{z}/{x}/{y}.png". It can contain an {api_key} or {accessToken} placeholder.
  • xyzservices: any provider object, for example basemap=xyz.OpenTopoMap (pip install "roadstyle[basemaps]").
  • Your own, by name: register it once, then use basemap="mytiles" and list it in basemaps=.
rs.register_basemap(rs.Basemap("mytiles", "My tiles",
                               "https://tiles.example.com/{z}/{x}/{y}.png", "© My tiles",
                               maxzoom=18))   # its last zoom level with tiles (default 19)

A tile URL, an xyzservices provider and a base map that you register use the first key that roadstyle finds. The base maps of roadstyle never take a key.

order source example
1 the call rs.render_edges(edges, api_key="pk.…")
2 the session, this provider, then any provider rs.set_api_key("pk.…", provider="mapbox"), rs.set_api_key("…")
3 settings, this provider, then any provider {"config": {"api_keys": {"mapbox": "…"}, "api_key": "…"}}
4 environment, this provider MAPBOX_ACCESS_TOKEN (suffixes _API_KEY, _ACCESS_TOKEN, _TOKEN, _KEY)
5 environment, any provider ROADSTYLE_API_KEY

Settings keep keys out of your code: put them in ~/.config/roadstyle/roadstyle.json.

See also: Style the roads · Every parameter · Command line