Skip to content

Highway Shields ​

Country-aware route markers driven by the network attribute on transportation and transportation_name.

Why this matters ​

A road tagged M1 looks completely different in:

  • US (M1 = motorway in NY) → black-on-yellow oval
  • UK (M1 = London-Leeds motorway) → blue-on-white pill
  • Germany (no M1) → not applicable

Our Lua tile pipeline classifies every road's network from its OSM tags, so styles can render the right shield without parsing ref strings on the client.

Sprite ​

Required sprite — hosted at /sprites/shields?key=…. Each icon is named after its network:

Sprite nameNetwork valueVisual
shield-us-interstateus-interstateRed/blue/white pentagon
shield-us-highwayus-highwayBlack-on-white shield
shield-us-stateus-stateBlack-on-white circle/square
shield-de-bundesautobahnde-bundesautobahnBlue rectangle "A"
shield-de-bundesstrassede-bundesstrasseYellow rectangle "B"
shield-gb-motorwaygb-motorwayBlue pill "M"
shield-gb-trunkgb-trunkGreen pill "A"
shield-fr-autoroutefr-autorouteRed pill "A"
shield-fr-route-nationalefr-route-nationaleRed rectangle "N"
shield-e-roade-roadGreen rectangle "E"
shield-asian-highwayasian-highwayBlue rectangle "AH"
shield-roadroad (fallback)Generic white pill

Style layer ​

json
{
  "id": "highway-shields",
  "type": "symbol",
  "source": "mfd",
  "source-layer": "transportation_name",
  "filter": ["all",
    ["has", "ref"],
    ["match", ["get", "class"], ["motorway", "trunk", "primary"], true, false]
  ],
  "layout": {
    "icon-image": [
      "concat", "shield-",
      ["coalesce", ["get", "network"], "road"]
    ],
    "icon-size": ["interpolate", ["linear"], ["zoom"], 8, 0.5, 16, 1.0],
    "icon-text-fit": "both",
    "icon-text-fit-padding": [1, 4, 1, 4],
    "text-field": ["get", "ref"],
    "text-font": ["Noto Sans Bold"],
    "text-size": ["interpolate", ["linear"], ["zoom"], 8, 9, 16, 13],
    "symbol-placement": "line",
    "symbol-spacing": 200
  },
  "paint": {
    "text-color": "#000",
    "text-halo-color": "#fff",
    "text-halo-width": 0
  }
}

Fallback chain ​

Some refs span countries (e.g. E-roads E40, AH-roads AH1). The Lua classifier picks the most specific country network when present, falls back to international networks (e-road, asian-highway), then to road.

If network is null, sprite name shield-road is used — always exists.

Custom sprite (your own brand) ​

Replace the hosted sprite with yours:

json
"sprite": "https://your-cdn.example.com/my-shields/v1"

Names must match the network values exactly: shield-us-interstate.png, etc.

Generate from SVG with spreet:

bash
spreet ./shields-svg/ ./output/my-shields
# produces my-shields.png + my-shields.json

Status ​

Shield rendering ships in style v1.1 (estimated 2026-05). Until then the network attribute is in tiles but the hosted style renders simple text refs.