Musette Data interface

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".

InputStatusDetail
positionsRequired 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.
routeRequired Course polyline as parallel arrays — distance (km), lat, lon, elevation (m); ~20 m spacing. Plus checkpoints: start, sprints, categorised climbs, finish.
riders / teamsRequired Bib, name, team, nationality, jersey, status. Team kit colours — they are what makes a peloton legible at distance.
classificationsOptional Official stage result and general classification. Used where present; the race renders without them.
groups / events / mediaOptional 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.

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:

4 · Latency

For a live stage, end to end, on the current implementation:

StageTypical
ingest → recomputed race state2.5–3.5 s per cycle, on a 5 s loop
viewer pollevery 5 s
playback buffer behind the live head15 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.