Live Timing is offline-first. The UI reads from IndexedDB; the network is a sync target, not a dependency.Documentation Index
Fetch the complete documentation index at: https://docs.time2.bike/llms.txt
Use this file to discover all available pages before exploring further.
The five layers
- UI — reads only from IndexedDB.
- Local event log (IndexedDB, append-only) —
{ clientEventId, sessionId, kind, payload, localTimestamp, clockOffset, syncedAt? }. - Materialized state — per-participant timing record, rebuilt by replaying the log. Surviving a tab refresh “for free” falls out of this.
- Sync worker — drains unsynced rows, POSTs them, marks
syncedAt. Idempotent viaclientEventId. Background Sync on Chromium; in-page worker fallback elsewhere. - Live broadcast — when online, the server fan-outs accepted events to other devices in the same session via SSE.
Sync indicator
Top-right pill on the operator screen:- 🟢 synced — IndexedDB and server agree.
- 🟡 N queued — N events in IndexedDB not yet uploaded.
- 🔴 OFFLINE — recording locally — no network detected. Everything you record is safe; it’ll drain when connectivity returns.
What survives a disaster
| Scenario | Outcome |
|---|---|
| Tab refresh | UI rebuilds instantly from IndexedDB. |
| Wi-Fi drops mid-race | Recording continues; events queue locally. |
| Phone dies, you swap in a new phone | New phone re-fetches the server state and resumes from seq. Anything on the dead phone that didn’t upload is lost — see Rescue export below. |
| Browser evicts IndexedDB | Lost. Mitigate by hitting Export log periodically. |
| Server restart | No data loss; events replay from MongoDB. |
Rescue export
The footer of the operator screen has Export log (CSV / JSON) buttons. These dump your local IndexedDB log to a file you can hand to the race director if the device dies before draining. The director can replay it via the bridge POST endpoint.When sync engine retries
- On
onlineevent (network restored). - On
visibilitychange(tab returning to foreground). - Every 5 seconds while running.
- On the Service Worker’s Background Sync push (Chromium).
clientEventId.
Resume after long offline
When a device comes back online after a long offline period, the SSE stream reconnects, and aGET /timing/:sessionId/events?since=N request fetches anything the device missed. The reducer merges; the UI updates.