Files
time_to_leave/README.md
T

5.8 KiB

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

  1. Add events — Manually enter events or import from an ICS calendar URL.
  2. Pick an origin — Use your current location or search for a departure station.
  3. Get journey info — The app queries ÖBB for real-time train schedules and optionally calculates bicycle routes via OSRM.
  4. 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