The SvelteKit 3 / Svelte 5 dashboard for Montréal and Ottawa in English and French. It reads versioned public snapshots and never queries PostgreSQL.
| Reference | Value |
|---|---|
| Subject and boundary | Web data layer, state ownership, routes, metadata and analytics. Feature internals are on the feature pages linked below; serving on ‣. |
| Verified source | apps/web at main 9733eb26d92533f56cdc8bc46b81b93fbb5987c8, checked November 10, 2026. Web /health reported commit 9733eb26 on November 10, 2026. Design pin (v0.40.0, #738) and the content-sections paragraph re-checked at main ed25527f on 2026-11-10. |
| Support state | Implemented source. The matching web workflow includes production deployment; runtime receipts are distinct from source verification. |
flowchart LR
C[providers.json catalog] --> BOOT[lib/v1/boot.ts<br/>city selection]
BOOT --> AD[lib/v1/adapter<br/>discovery + validation]
AD --> REPO[lib/v1/repositories<br/>live, static, historic]
REPO --> RES[resource.svelte.ts<br/>keyed, fenced resources]
REPO --> LIVE[live/store.svelte.ts<br/>polling]
RES --> SEL[feature selectors]
LIVE --> SEL
SEL --> UI[sections and components]
| Owner | Responsibility |
|---|---|
lib/v1/adapter/ |
Manifest discovery, transport and runtime validation of every payload |
lib/v1/http.ts, serverContext.ts, binding.ts |
Fetch seam, timeouts and errors; on the server, the SNAPSHOTS binding (served through the data proxy's own snapshot-response.js) with DATA service fallback |
lib/v1/schemas/ |
Zod parsers for every payload; types generated from the mirrored JSON Schemas in schemas/json, with generated-contract and handwritten conformance tests keeping them aligned |
lib/v1/resource.svelte.ts |
Keyed state, seeds, cancellation and stale-result fencing: a late response whose key differs from the active key never commits |
lib/v1/live/store.svelte.ts |
Shared clock, manifest TTL, per-family feed health and capture-age policy, retained failures, pause when hidden or offline. createLiveStore(manifest, reader, options) reads through an injected LiveReader |
lib/v1/boot.ts, providers.ts |
Catalog-driven city selection and explicit discovery failure |
lib/filters/ |
Requested filter state and URL encoding |
lib/features/<surface>/ |
Selectors, copy, sections and colocated tests per surface |
Provider, entity and selected range are always part of request identity, so switching cities cannot show another city's data.
Each module owns one decision behind a small interface; components consume its result instead of re-deriving it.
| Module | Interface | Owns |
|---|---|---|
| livePresentation.ts | livePresentation(input), feedPresentation, publicationPresentation, stampAgeText |
Feed health presentation: age text, age source (publication or serving capture) and the Live notice kind: none, report-behind, refresh-unavailable, partial-stall, whole-feed-stall, unavailable, no-vehicles |
| absence.ts | liveAbsenceReason, describeAbsence, absenceShort, absenceSentence, provideLiveAbsenceContext / readLiveAbsenceContext |
Missing-data reasons and their EN/FR copy. Feed health wins over a single vehicle's silence; an unsupported family maps to metro-no-realtime |
| verdict.ts | reliabilityVerdict(file, window, copy) |
The Verdict: at least 30 observations, Reliable from 80%, Patchy from 60% |
| store.svelte.ts | createLiveStore(manifest, reader, options) |
Live reading seam. Production passes the adapter's liveReader; tests pass the fixture reader |
| polling.ts | livePollDelayMs(headers, ttlMs) |
Refetch timing follows the cache: the remaining max-age minus Age, plus 0.5 to 2 s of jitter, clamped between 5 s and the manifest TTL. Without readable headers it waits one TTL |
All pages live under routes/[[lang=locale]]/ (English at /, French at /fr): home, map, network, lines and lines/[id], stops and stop/[id], trip/[id], alerts, hotspots, repeat-offenders, receipt, metrics, status, search, plus accessibility, privacy and terms. The status page uses rider-facing wording and counts out-of-service vehicles (vehicles without a trip) from the live vehicles file (vehicleService.ts). route/[id] answers GET and HEAD with a 301 redirect to the same locale's lines/[id], keeping the query string. Feature pages: Home directory · Map interface · Stop detail · Trip detail.
on_time with delay_min=1; rounded minutes cannot reconstruct published status, and an unknown status never fills in a missing delay.SectionsToggle supplies localized copy to the design v0.40.0 bulk control (#738). A page with at least two eligible content sections and the control starts every section expanded on a first visit (no stored choice, or a malformed one), with the control neutral and labelled Collapse all; the TOC card starts open. A stored Collapse all collapses content across pages and visits (remembered-sections.spec.ts). Bulk Expand all / Collapse all stores expanded/collapsed in localStorage sections-choice, shared across pages and visits. Individual toggles apply only to the current view. Fragment navigation can reveal its target without changing the saved bulk choice.
Independent panels and map tools are outside this preference and bulk count/action. Map layout settings have their own keys. The EN/FR device-storage copy describes the section preference alongside theme, motion and map layout in localStorage, and navigation scroll positions in sessionStorage.
The boot script prepares first-paint section geometry before app initialization. Server HTML contains readable bodies; on code failure or a five-second initialization stall, recovery reveals pending sections and hides/disables incomplete bulk controls. The saved bulk preference is unchanged by recovery. Storage access errors do not throw; persistence requires usable localStorage.