- Python 51.4%
- TypeScript 47.4%
- CSS 0.5%
- JavaScript 0.3%
- HTML 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
find_direct_journeys filtered latest_arrival by comparing the raw HHMM arrival string, so an overnight service (e.g. departs 23:45, arrives 04:21 the next day) satisfied "arrive by 07:00" purely because 04:21 is numerically less than 07:00 - its real arrival is a calendar day later than intended. Same gap existed in the two places find_interchange_journeys/find_via_journey build a synthetic cross-London transfer leg as an itinerary's final leg, which don't route through find_direct_journeys' check at all. Found while manually testing MKC->DWL via WAT with a tight arrival window, which returned services arriving the following dawn; confirmed the same wrong results also came from the plain non-via auto-search, so this predates and is independent of the via-routing fix. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
| .impeccable | ||
| backend | ||
| frontend | ||
| raildata-sftp | ||
| .gitignore | ||
| CLAUDE.md | ||
| compose.yml | ||
| DESIGN.md | ||
| PRODUCT.md | ||
| README.md | ||
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.