No description
  • Python 52.4%
  • TypeScript 46.5%
  • CSS 0.5%
  • JavaScript 0.3%
  • HTML 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Jason Artemis Winstanley b290d6b770
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled
Fix unbounded overdue-delay fallback and backfill nonsense archived data
overdue_mins in process_service computed now() - booked_departure with no
cap, which is fine for a live train still not-yet-departed today but
produced multi-day "delays" (thousands of minutes) when reprocessing an
already-completed historical service days later — exactly what happened
when the new backfill_archived_data.py script tried to refresh archived
trains via schedule_cache, whose CIF-first lookup returns booked-only
data once trust_movements has rolled past its 3-day retention.

Added backfill_archived_data.py, calling RTT directly (bypassing
schedule_cache/CIF, which has no realtime concept at all) since RTT's
own historical response carries realtimeActual/realtimeForecast for
completed past services — the only surviving source of real delay data
past the trust retention window. Ran it once to backfill/repair 15
archived trains that were missing final_boarding_departure or had
bogus multi-day final_delay_minutes values.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jTxHgeU1EQVk1MzsbyRF3
2026-09-03 06:16:34 +00:00
.github/workflows Add CI workflow, request metrics, live-batch polling, and archived departure time 2026-09-03 06:04:37 +00:00
.impeccable Initial commit of Skyewatch 2026-07-28 19:58:59 +00:00
backend Fix unbounded overdue-delay fallback and backfill nonsense archived data 2026-09-03 06:16:34 +00:00
frontend Add CI workflow, request metrics, live-batch polling, and archived departure time 2026-09-03 06:04:37 +00:00
raildata-sftp Initial commit of Skyewatch 2026-07-28 19:58:59 +00:00
.gitignore Initial commit of Skyewatch 2026-07-28 19:58:59 +00:00
CLAUDE.md Initial commit of Skyewatch 2026-07-28 19:58:59 +00:00
compose.yml Add CI workflow, request metrics, live-batch polling, and archived departure time 2026-09-03 06:04:37 +00:00
DESIGN.md Initial commit of Skyewatch 2026-07-28 19:58:59 +00:00
HANDOFF.md Add passing train departure filter and native API auth 2026-08-11 13:22:23 +00:00
PRODUCT.md Initial commit of Skyewatch 2026-07-28 19:58:59 +00:00
README.md Add README 2026-07-29 19:36:06 +00:00

Skyewatch

Skyewatch (aka Train Tracker) is a full-stack web app for monitoring UK railway services in real time. Add a train by headcode and see its live status, delays, current location, and per-stop calling points — glanceable enough to answer "is my train OK?" at a glance, with richer detail (timelines, delay history, disruption context) available for anyone who wants to dig in.

Features

  • Add trains by headcode, Service UID, or station departure board search — with live status, delay, current location, and platform.
  • Per-stop timelines showing booked vs. actual times all the way along a service's route.
  • Recurring trains for a regular commute, with bank-holiday-aware exceptions.
  • Journey planning — direct and interchange routes from the local timetable, with live delay data factored into whether a connection is actually catchable.
  • Notifications via Discord DM, Telegram, and Web Push — delays, cancellations, boarding/arrival, off-route alerts.
  • Punctuality stats and an archive of past journeys.
  • Household view — see other household members' trains for today.
  • Public share links for a single tracked train, no login required.
  • Disruption dashboard (TfL + National Rail), when configured.
  • Discord bot integration — slash commands, DM notifications, OAuth login.

Architecture

React 18 + Vite (nginx)
    ↕ HTTP/JSON
FastAPI + SQLAlchemy (Python 3.12)
    ↕ psycopg2
PostgreSQL 16

Live data comes primarily from a locally-ingested CIF full timetable feed (Rail Data Marketplace), overlaid with Darwin Push Port real-time movement events consumed continuously via Kafka — not the Realtime Trains (RTT) API, which is used only as a fallback when the local data has no match. See CLAUDE.md for the full data-pipeline design.

An MCP (Model Context Protocol) server is also exposed, so an AI assistant can look up live train status, search departures, plan journeys, and manage tracked trains on the user's behalf.

Running it

Requires Docker Compose. Copy .env.example (if present) or otherwise populate a .env file with the required credentials — see CLAUDE.md's Environment Variables section for the full list (database password, JWT secret, RTT/Darwin/NROD/Discord/Telegram/Web Push credentials, etc.).

docker compose up           # start the full stack (db, backend, frontend, raildata-sftp)
docker compose build        # rebuild images after a code change

The raildata-sftp service receives the daily CIF timetable push from Rail Data Marketplace; the backend watches for new files and ingests them automatically.

Frontend only

cd frontend
npm install
npm run dev      # Vite dev server, proxies /api → localhost:8000
npm run build    # TypeScript check + production build

Backend only

cd backend
alembic upgrade head
uvicorn app.main:app --host 0.0.0.0 --port 8000

Contributing / development notes

See CLAUDE.md for the full architecture write-up, data pipeline design, backend/frontend file structure, and the conventions this codebase follows (timezone handling, sync-vs-async DB access, JSON column mutation, etc.) — required reading before making non-trivial changes.