What we need, what we derive, and what happens when the feed breaks.
Reference for the technical side of an integration. Two screens, no pitch. The commercial framing is on the broadcaster page.
1 · What we need from you
One load-bearing input, and three supporting ones. Everything crosses a single boundary — a provider that answers "give me the stage" and, for a live stage, "is there anything new".
| Input | Status | Detail |
|---|---|---|
| positions | Required | Per rider, per tick: distance along the course and a timestamp. Speed and lateral offset are used when present. One sample per rider every ~6 s is sufficient; we interpolate between ticks, so do not resample or densify. |
| route | Required | Course polyline as parallel arrays — distance (km), lat, lon, elevation (m); ~20 m spacing. Plus checkpoints: start, sprints, categorised climbs, finish. |
| riders / teams | Required | Bib, name, team, nationality, jersey, status. Team kit colours — they are what makes a peloton legible at distance. |
| classifications | Optional | Official stage result and general classification. Used where present; the race renders without them. |
| groups / events / media | Optional | If your feed already publishes curated groups or a commentary ticker we will show them — but see the next section: we do not need them. |
Two units traps, from experience. Rider odometers are
often delivered as distance to finish; distance along route is
stageLength − distanceToFinish. And fields named
"km-something" are frequently in metres. Both are worth
checking before mapping.
2 · What we derive without being given it
Gaps, group composition and splits are computed by Musette from positions. They are not required as input, and where your feed supplies them we do not depend on them. This is the part that carries the value: a feed of coordinates becomes a readable race.
- Group structure — which riders are together on the road at each moment, and the kind of group it is (break, chase, peloton, dropped, solo).
- Gaps — time between every pair of adjacent groups, and to the race leader, continuously.
- Splits and merges — the moment a group fractures or a chase makes contact, with the evidence that triggered the call attached to it.
- Race order — position on the road at any instant, independent of any published classification.
- Terrain context — gradient and climb position under each group, from the route profile.
Because none of this is taken from an editorial layer, your own editorial timeline stays an independent check on it rather than its source.
3 · When the feed drops
The failure modes we have actually hit, and what each does:
- Short gap (up to ~2 min). Positions are interpolated across it and the tick is marked estimated rather than measured. The distinction is kept in the data, not smoothed away.
- Long gap. Riders are carried along the course centreline rather than frozen or teleported, and the samples stay flagged as estimated. A long enough gap is visible as such.
- Reconnect. Feeds that re-send a full snapshot on reconnect self-heal completely — the document state is whole again on the next message. Single-shot telemetry sent once and never repeated does not: whatever was missed during the outage is gone, and we say so rather than reconstructing it.
- Out-of-order and duplicate ticks. Both occur in production feeds. Records are de-duplicated on an update key and non-advancing ticks are dropped, keeping first arrival.
- Bad positions. GPS glitches — a rider apparently at 60 km/h through a hairpin, or across a field — are rejected and back-filled rather than rendered.
4 · Latency
For a live stage, end to end, on the current implementation:
| Stage | Typical |
|---|---|
| ingest → recomputed race state | 2.5–3.5 s per cycle, on a 5 s loop |
| viewer poll | every 5 s |
| playback buffer behind the live head | 15 s |
| position in feed → on screen | ~20–30 s |
The 15 s buffer is deliberate: interpolation needs a tick on both sides, and it absorbs feed jitter without stuttering. It is configurable, and shrinking it trades smoothness for latency. Cold start of the live pipeline is 13–21 s; steady-state memory is well under a gigabyte for a full stage.
These figures are from a single-box deployment reconstructing a whole stage on every cycle — an implementation choice that favours correctness over incrementality. Both are improvable; neither has needed improving yet.
5 · Provenance of what is on this site
The stages published here were captured live from the publicly reachable Tour de France race-centre feed during the 2026 race, under no agreement with the organiser or any technology partner. Some captures have gaps where that public feed went quiet, and one stage lost its finish entirely because the capture window closed before a late start had finished.
Every sample is kept marked as measured or reconstructed, and the guided stage prints its own figure on the page — computed from that stage's samples, not asserted. For reference, the reconstructed share on a clean capture runs at about 3%.
None of the derived behaviour above depends on that source. On your feed it is the same pipeline with a different provider at the boundary.