Skip to content

bfeitknecht/FunWeb-final-project

Repository files navigation

Visualize Zurich's Public Transport Network

A web application visualizing Zurich's public transport network with approximated vehicle positions, interactive mapping, and route planning.

Features: Interactive transit line visualization | Nearby departures | Approximated vehicle positions | Connection planning

Tech: Next.js 16 · React 19 · FastAPI · PostgreSQL · MapLibre GL · GTFS · Docker · Kubernetes

Backend

  • Prereqs: Docker + Docker Compose.
  • Data: place GTFS static files under backend/staticData/gtfs_fp2025_20251203 (directory with stops.txt, trips.txt, stop_times.txt, routes.txt, agency.txt, shapes.txt, plus stops_zurich.txt for filtering and routes_zurich.txt for colors, these two files should be in /staticData).
  • Build backend image (installs DB deps): docker compose build backend
  • Start PostgreSQL: docker compose up -d postgres
  • Reset schema (optional, wipes data): docker compose exec -T postgres psql -U postgres -d postgres -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
  • Apply schema: docker compose exec -T postgres psql -U postgres -d postgres < backend/db/gtfs_postgres.sql
  • Load GTFS into PostgreSQL (uses Zurich color mapping, falls back to red/black when missing):
    • Directory input: docker compose run --rm backend python load_gtfs.py --gtfs-path staticData/gtfs_fp2025_20251203
    • Zip input: docker compose run --rm -v "$PWD/path/to/gtfs.zip:/data/gtfs.zip" backend python load_gtfs.py --gtfs-path /data/gtfs.zip
  • Run services: docker compose up (backend on http://localhost:8080, database can be accessed at http://localhost:8081)
  • Sample endpoints:
    • GET /gtfs/routes
    • GET /gtfs/stops (optional q, limit, offset)
    • GET /gtfs/stops/{stop_id}
    • GET /gtfs/trip/{trip_id}/stops

Run Locally (quick start)

  1. Prereqs: Docker + Docker Compose.
  2. Clone repo and ensure GTFS static files are present at backend/staticData/gtfs_fp2025_20251203 (directory with stops.txt, trips.txt, stop_times.txt, routes.txt, agency.txt, shapes.txt, and stops_zurich.txt), unzipped.
  3. Build backend (installs DB deps and copies code): docker compose build backend
  4. Start PostgreSQL: docker compose up -d postgres
  5. (Optional) Reset + apply schema:
    docker compose exec -T postgres psql -U postgres -d postgres -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
    docker compose exec -T postgres psql -U postgres -d postgres < backend/db/gtfs_postgres.sql
  6. Load GTFS into PostgreSQL (directory input): this can take quite some time (took ~10 minutes on an M1 Pro)
    docker compose run --rm backend python load_gtfs.py --gtfs-path staticData/gtfs_fp2025_20251203
  7. Bring up backend/frontend: docker compose up (backend at http://localhost:8080, frontend at http://localhost:3000)
  8. Smoke test: curl http://localhost:8080/gtfs/routes or curl http://localhost:8080/gtfs/stops/<stop_id>

Manual data prep (schema + realtime cache)

  • Apply schema (one-time or after reset): docker compose exec -T postgres psql -U postgres -d postgres < backend/db/gtfs_postgres.sql
  • Run weekly GTFS fetch + load (downloads feed, processes, loads DB): docker compose run --rm backend python weekly_run.py
  • If you only need static GTFS loaded from existing files: docker compose run --rm backend python load_gtfs_to_db.py --gtfs-path staticData/GTFS

API Endpoints

  • GET /gtfs/routes - All transit routes with colors
  • GET /gtfs/stops?q=<query> - Search stations (autocomplete)
  • GET /gtfs/stops/{stop_id} - Single station details
  • GET /gtfs/realtime/positions - Cached vehicle positions
  • GET /gtfs/realtime/positions/stream - SSE stream of live positions
  • GET /gtfs/realtime/vehicles - Vehicle summaries with delays
  • POST /gtfs/user-location - Nearby departures by geolocation
  • GET /connections?from=X&to=Y - Route planning (proxies Swiss Transport API)

Architecture

Frontend: Next.js app with MapLibre GL for interactive maps, React Context for state management

Backend: FastAPI approximating vehicle positions based on schedules, real-time delay data, and route geometries. Route geometries are served from a static WGS84 GeoJSON file for frontend rendering.

Database: PostgreSQL storing GTFS data (filtered Zurich stops, routes, trips, stop_times, shapes)

Deployment: Docker containers orchestrated by Kubernetes with Helm charts, automated CI/CD via GitLab

Technical Report

The technical report is available in report/.

Compile:

cd report/
pdflatex report.tex
bibtex report
pdflatex report.tex
pdflatex report.tex

Team

ETH Zürich – Fundamentals of Web Engineering, 2025