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.

Data layer

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.

Deep modules

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

Routes

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.

Display rules shared by every surface

Content sections and device storage

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.

Entity cards, listing grid and shared controls