6.6 Routes Pages
The Routes section now exposes two views through a shared server-rendered shell:
/routes: the route browser for comparing Atlas GTFS and OSM route definitions/routes/gtfs-stop-id-sloid: a diagnostic map for the canonical GTFSstop_id<-> ATLASsloidmapping
Both views are rendered through templates/pages/routes.html with an active_view switch, so the page keeps one shared tab layout while loading view-specific data and JavaScript.
1. Shared Shell and Routing
backend/blueprints/routes.py provides:
routes_page()for the route list tabroutes_gtfs_stop_id_sloid_page()for the GTFS diagnostic map tab_render_routes_template()to pass shared tab state and GTFS map limits into the template
The template renders page tabs at the top and then chooses between:
- the existing filterable route-card UI
- the GTFS map shell with summary overlay, banner, and full-size Leaflet map container
2. Route Browser Tab
The default /routes tab is still designed around two primary filter dimensions plus free-text route search:
- Atlas Operator (index-style searchable multi-select dropdown)
- Status (
all,matched,unmatched,unmatched_atlas,unmatched_osm)
End-to-end flow
- User submits filters using the top toolbar.
- Flask route [
backend/blueprints/routes.py](https://github.com/openTdataCH/stop_sync_osm_atlas/blob/main/backend/blueprints/routes.py)::routes_pagenormalizes query params. - Backend builds a combined route query and applies matched-state filters, optional Atlas operator constraints, and optional route-id search.
- Matched pairs are returned once, then unmatched Atlas-only and OSM-only rows are appended into the same paginated result set.
- Results are expanded with route-stop details, itinerary matches, and route metadata.
- Template
templates/pages/routes.htmlrenders compact route cards. - Each card starts collapsed and can be unfolded to inspect stops by direction or preview route position on an embedded map.
Stops and embedded map rendering
Stops are loaded from:
- normalized
stop_callsjoined back toatlas_stops,osm_nodes, andstops_matched
Direction groups are sorted numeric-first, then grouped by uic_ref for a compact two-level stop rendering.
The embedded route preview map reuses the shared main-map stack:
- the card exposes a route-scoped
/api/datafilter payload - markers use shared map helpers (
createAtlasMarker,createOsmMarker) - bounds are fit after the route points load
3. GTFS stop_id <-> sloid Map Tab
The /routes/gtfs-stop-id-sloid tab is a full-page diagnostic Leaflet map backed by the imported gtfs_stops_raw and gtfs_stop_identity_resolution tables.
What it shows
- GTFS stops with at least one imported coordinate source
- ATLAS stops represented in the imported GTFS/ATLAS state table
- visible matched line segments between GTFS and ATLAS points
- a compact summary overlay showing GTFS coverage, ATLAS coverage, and assignment counts
Marker colors are intentionally fixed:
- matched ATLAS: blue
- unmatched ATLAS: red
- matched GTFS: green
- unmatched GTFS: gray
Backend APIs
The tab reads three dedicated JSON endpoints from backend/blueprints/routes.py:
/api/routes/gtfs-stop-id-sloid/summary/api/routes/gtfs-stop-id-sloid/map/api/routes/gtfs-stop-id-sloid/popup
The query and serialization logic lives in backend/services/gtfs_stop_id_sloid.py.
That service builds deduplicated coordinate subqueries from gtfs_stop_identity_resolution, computes matched/unmatched counts per side, and returns:
gtfs_stopsatlas_stopsmatchesmeta(zoom, cap state, overview/detail mode)
Overview/detail behavior
The map uses two density modes:
- overview mode below zoom
11: limit3000GTFS rows and3000ATLAS rows - detail mode at zoom
11and above: limit5000GTFS rows and5000ATLAS rows
Rows are fetched in a balanced way so matched and unmatched states do not starve each other inside a dense viewport.
Popup behavior
The frontend lazy-loads popup payloads per clicked marker.
GTFS popups include:
- stop identifiers and coordinates
- matched SLOID previews
- same-UIC ATLAS candidate previews
ATLAS popups include:
- SLOID and ATLAS metadata
- matched GTFS stop previews
- same-UIC GTFS candidate previews
The map keeps the shared draggable multi-popup behavior by reusing the common popup helpers and line handler logic.
4. Files and Responsibilities
backend/blueprints/routes.py- route-list query construction and pagination
- GTFS tab page route and three GTFS JSON endpoints
- shared routes template rendering
- loading
line_families,line_family_matches,itineraries,itinerary_matches, andstop_callsfor route cards
backend/services/gtfs_stop_id_sloid.py- GTFS summary payloads
- viewport payloads for GTFS/ATLAS markers and line segments
- GTFS and ATLAS popup payload builders
templates/pages/routes.html- tab shell shared by both Routes views
- route list toolbar, cards, and pagination
- GTFS map shell, banner, and summary overlay host
static/js/pages/routes.js- route browser toolbar behavior and embedded route preview maps
static/js/pages/routes-gtfs-stop-id-sloid.js- GTFS map initialization, viewport fetching, marker rendering, summary updates, and popup loading
5. Maintenance Guidelines
- Keep the canonical GTFS
stop_id<->sloidmatcher inmatching_and_import_db/downloader/get_atlas_gtfs.py. - Keep GTFS map query logic in
backend/services/gtfs_stop_id_sloid.py, not in the template or page controller. - Keep the Routes tab shell shared; add view-specific behavior behind
active_viewrather than splitting into parallel templates. - Preserve the fixed marker-color semantics because they are part of the debugging vocabulary used elsewhere in the docs.