Rewrite of the departures board for Ile-de-France Mobilites train data app from original author: https://x0r.fr.
- Python 3.12+
- FastAPI
- Jinja templates
- Vanilla JavaScript
- Docker for deployment
The old Perl/Dancer + PostgreSQL + GTFS import pipeline has been replaced with a smaller FastAPI app that is easier to run and maintain.
Preserved behavior:
- station selection with
/?s=CODE - live departures board
- station autocomplete
- line filtering
- saved station cookie
- compatibility endpoints:
/jsonand/autocomp
Improvements:
- typed configuration from environment variables
- explicit handling for invalid token, rate limits, upstream failures, and empty results
- health endpoint at
/health - simpler deployment with Docker
- cleaner responsive UI
- structured Python service layer and tests
- The rewrite intentionally removes the legacy PostgreSQL + GTFS schedule database to avoid the largest operational burden in the original project.
- The app still shows planned and expected departure times from the live IDFM payload when available.
- Downstream stopping patterns from the old GTFS enrichment are not rebuilt in this version, so
dessertescurrently falls back toDesserte indisponible. - A compact station dataset is bundled from the legacy repository data. A small number of stations in that snapshot do not have a usable real-time stop-area reference and will return a clear message instead of departures.
- Line reference mapping is bundled from the SNCF GTFS routes dataset so line badges and filters still work without keeping a live GTFS database.
Required:
IDFM_API_TOKEN: API token forprim.iledefrance-mobilites.fr
Optional:
APP_ENV: application environment, defaultdevelopmentHOST: bind host, default0.0.0.0PORT: bind port, default8000LOG_LEVEL: logging level, defaultINFODEFAULT_STATION: default station code, defaultGDSCACHE_TTL_SECONDS: upstream cache TTL, default20REQUEST_TIMEOUT_SECONDS: upstream request timeout, default8MAX_DEPARTURES: number of departures to display, default6
See .env.example.
- Copy
.env.exampleto.env. - Set
IDFM_API_TOKENin.env. - Install dependencies:
python -m pip install -e .[dev]- Start the app:
python -m appOpen http://127.0.0.1:8000.
For auto-reload during development:
python -m uvicorn app.main:app --reload --host 127.0.0.1 --port 8000Build and run with Docker Compose:
docker compose up --build -dOr plain Docker:
docker build -t rer-web .
docker run --env-file .env -p 8000:8000 --restart unless-stopped rer-webThe container binds to HOST and PORT from the environment. For a standard reverse proxy setup, keep HOST=0.0.0.0 and proxy to the configured PORT.
/: HTML app/json: legacy-compatible departures JSON/api/departures: canonical departures JSON/autocomp: legacy-compatible station autocomplete JSON/api/stations/autocomplete: canonical station autocomplete JSON/health: health check
python -m pytestThe footer now shows:
ketah.infoOriginal author: https://x0r.fr
