6.6 Routes Pages
The Routes section exposes three views through a shared server-rendered shell:
/routes: the route browser for comparing ATLAS GTFS and OSM route definitions/routes/non-gtfs: OSM public transport routes that do not appear in the OpenTransportData GTFS dataset and are excluded from route matching/routes/gtfs-stop-id-sloid: a diagnostic map for the canonical GTFSstop_id↔ ATLASsloidmapping
All three 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 tabnon_gtfs_routes_page()for the non-GTFS route 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 filterable route-card UI
- the non-GTFS 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 provides these filters and controls:
- ATLAS Operator (searchable multi-select dropdown)
- OSM Route Operator (searchable multi-select dropdown)
- Status (
all,matched,unmatched,unmatched_atlas,unmatched_osm) - results per page (5, 10, 20, 50, or 100)
- free-text route search
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 and OSM 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. Non-GTFS Routes Tab
The /routes/non-gtfs tab lists OSM route families marked is_non_gtfs. These routes are retained for inspection but are not included in ATLAS–OSM route matching. The tab reuses the route cards, stop details, embedded maps, and pagination shell from the main browser, but intentionally omits the main browser's search, status, and operator toolbar.
4. 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: orange (
#F0AD4E; described as yellow in the UI legend) - unmatched GTFS: gray
Backend APIs
The tab reads four 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/search/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.
Identifier search
The search endpoint accepts exact SLOID, UIC, and GTFS stop_id searches. It returns mappable targets, after which the frontend centers the map and reloads the viewport with the identifier filter applied.
5. Files and Responsibilities
backend/blueprints/routes.py- main and non-GTFS route-list query construction and pagination
- GTFS tab page route and four 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
6. 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.