Navvo
Guides

Show a live traffic layer

Render real-time congestion on your map, loaded efficiently by tile-cover.

Show a live traffic layer

Overlay real-time congestion — sourced from Navvo's own probe network — on your map. The pattern: compute the tiles covering your viewport, fetch each, and render the colored lines. Uses Traffic.

Scope required: traffic

Option A — GeoJSON tiles (style it yourself)

1. Get the tiles covering the viewport

GET /traffic/lines/tile-cover returns the exact tile URLs for a bbox:

const bounds = map.getBounds(); // Navvo Maps
const bbox = [bounds.getWest(), bounds.getSouth(), bounds.getEast(), bounds.getNorth()].join(",");

const cover = await (await fetch(
  "https://navvo.io/api/v1/traffic/lines/tile-cover?" + new URLSearchParams({ bbox, zoom: "14" }),
  { headers: { "x-api-key": KEY } }
)).json();
// cover.tiles -> [{ z, x, y, url }]

2. Fetch and merge the tiles

const features = [];
for (const t of cover.tiles) {
  const fc = await (await fetch(`https://navvo.io${t.url}`, { headers: { "x-api-key": KEY } })).json();
  if (fc.hasData) features.push(...fc.features);
}
const geojson = { type: "FeatureCollection", features };

3. Render with congestion colors

Each feature carries a color property keyed to its congestion level:

map.addSource("traffic", { type: "geojson", data: geojson });
map.addLayer({
  id: "traffic",
  type: "line",
  source: "traffic",
  paint: {
    "line-color": ["get", "color"],
    "line-width": ["interpolate", ["linear"], ["zoom"], 10, 1.5, 16, 5],
  },
});

Refresh every ~60 seconds (the layer descriptor's refreshSeconds).

Option B — Vector tiles (native Navvo Maps source)

The telemetry overlay also serves binary vector tiles, which Navvo Maps can consume directly without manual fetching:

map.addSource("traffic", {
  type: "vector",
  tiles: ["https://navvo.io/api/v1/telemetry/traffic-overlay/vector/{z}/{x}/{y}.pbf?mode=current"],
  minzoom: 8,
  maxzoom: 16,
});
map.addLayer({
  id: "traffic",
  type: "line",
  source: "traffic",
  "source-layer": "navvo_traffic",
  paint: {
    "line-width": 3,
    "line-color": [
      "match", ["get", "congestion"],
      "light", "#188038",
      "moderate", "#D9A441",
      "heavy", "#D94B4B",
      "blocked", "#8B1A1A",
      "#188038",
    ],
  },
});

Typical (predicted) traffic

For "what traffic usually looks like" rather than right now, use the predicted line tiles (GET /traffic/predicted/tiles/{z}/{x}/{y}) or the overlay with mode=typical.

A summary badge

For a single congestion read-out over an area, GET /traffic/summary returns a congestionScore, dominant level, and a per-level breakdown:

const s = await (await fetch(
  "https://navvo.io/api/v1/traffic/summary?bbox=" + bbox, { headers: { "x-api-key": KEY } }
)).json();
// s.conditions.summary -> "Slow moving"
Live congestion only covers roads with recent Navvo probe coverage. Where there's no data, hasData is false — fall back to the predicted/typical layer for a fuller picture.
Want to improve the traffic data your app sees? Contribute anonymous trips via Telemetry — see the Fleet & logistics guide.
Copyright © 2026