TimeToLeave
Know when to leave the house so you're never late for your next meeting.
TimeToLeave is a web app that tells you when to leave for upcoming events based on real-time Austrian train (ÖBB) schedules — and optionally compares train journeys with bicycle routes.
Features
- Real-time train journeys — Query the ÖBB HAFAS API for live departure times, delays, and platform information.
- Calendar import — Import events from any ICS calendar (CalDAV, Google Calendar, etc.).
- Bicycle routing — Compare train journeys with bicycle routes powered by OSRM, including distance, duration, and turn-by-turn directions.
- Train vs bicycle comparison — See both travel modes side by side for each event, so you can decide what works best.
- Calendar month view — Browse events in a month grid, see event indicators on dates, and drill into train/bike details per day.
- Geolocation support — Use your browser's current location as the origin station.
- Countdown & status indicators — Visual countdown timers and live status badges so you know exactly when to go.
Architecture
Built with Next.js App Router (v16), React 19, TypeScript, and Tailwind CSS v4.
src/
├── app/ # Next.js App Router pages & layout
│ ├── api/ # Server-side API routes
│ │ ├── hafas/ # ÖBB train journey search
│ │ ├── calendar/ # ICS calendar parsing
│ │ ├── geocode/ # Nominatim geocoding
│ │ ├── bike-route/ # OSRM bicycle routing
│ │ └── health/ # Server health check
│ ├── ui/ # Shared UI components
│ ├── page.tsx # Home page
│ └── layout.tsx # Root layout
├── hooks/ # Custom React hooks
│ ├── useJourneys.ts # Fetch train journeys per event
│ ├── useBikeRoute.ts # Fetch bicycle routes
│ ├── useCalendar.ts # Calendar import & parsing
│ ├── useEventsStore.tsx # Events state management
│ ├── useGeolocation.ts # Browser geolocation
│ ├── useOriginStation.ts # Origin station selection
│ ├── useClock.ts # Live clock for countdowns
│ └── useServerHealth.ts # API health monitoring
├── lib/ # Shared utilities & clients
│ ├── hafas-client.ts # ÖBB HAFAS API client
│ ├── geocoding-client.ts # Nominatim geocoding client
│ ├── bike-routing-client.ts# OSRM bicycle routing client
│ ├── calendar-utils.ts # ICS parsing utilities
│ ├── countdown-utils.ts # Countdown time calculations
│ ├── formatting.ts # Date/time formatting helpers
│ └── constants.ts # App-wide constants
├── types/ # TypeScript type definitions
└── test/ # Test utilities
Getting Started
Prerequisites
- Node.js 20+
- npm (or yarn / pnpm)
Installation
npm install
Development
npm run dev
The app will be available at http://localhost:3000.
Build & Start
npm run build
npm start
Docker Deployment
Build and run with Docker Compose:
docker compose up --build -d
The app will be available on port 3000 by default. Override the port or any other variable by creating a .env file at the project root:
PORT=8080
HAFAS_URL=https://fahrplan.oebb.at/bin/mgate.exe
NOMINATIM_URL=https://nominatim.openstreetmap.org
NOMINATIM_USER_AGENT=TimeToLeave/2.0
OSRM_URL=https://router.project-osrm.org
The Dockerfile uses a 3-stage build (deps → builder → runner) with output: "standalone", producing a small final image that runs as a non-root user. Stop and remove the container with docker compose down.
Testing
npm test # Run tests once
npm run test:watch # Run tests in watch mode
Linting & Type Checking
npm run lint
npm run typecheck
Environment Variables
The following environment variables can be configured (defaults are provided for development):
| Variable | Description | Default |
|---|---|---|
HAFAS_URL |
ÖBB HAFAS API endpoint | https://fahrplan.oebb.at/bin/mgate.exe |
NOMINATIM_URL |
Nominatim geocoding endpoint | https://nominatim.openstreetmap.org |
NOMINATIM_USER_AGENT |
User-Agent for Nominatim requests | TimeToLeave/2.0 |
OSRM_URL |
OSRM routing endpoint | https://router.project-osrm.org |
Tech Stack
| Category | Technology |
|---|---|
| Framework | Next.js 16 (App Router) |
| UI | React 19 + Tailwind CSS v4 |
| Language | TypeScript 5 |
| Train Data | ÖBB HAFAS API |
| Geocoding | Nominatim |
| Bicycle Routing | OSRM |
| Calendar | node-ical |
| Dates | date-fns |
| Testing | Vitest + React Testing Library |
How It Works
- Add events — Manually enter events or import from an ICS calendar URL.
- Pick an origin — Use your current location or search for a departure station.
- Get journey info — The app queries ÖBB for real-time train schedules and optionally calculates bicycle routes via OSRM.
- Decide when to leave — Each event shows a countdown, the best available train, and (if enabled) a bicycle alternative with estimated travel time.
License
MIT