fegger 3c6df95a86 Refactor monorepo structure and replace hardcoded colors
Add TypeScript project references, update ESLint configs to support
ESM modules, and introduce brand semantic color tokens across the web
app. Add comprehensive documentation for architecture, API reference,
development setup, and user guide.
2026-05-12 21:22:40 +02:00
2026-05-10 21:19:39 +02:00

⏱️ TimeToLeave

TimeToLeave Logo

TimeToLeave is a smart departure planner that tells you exactly when to leave home to catch your public transport for upcoming appointments. It syncs with your personal calendar, checks real-time train/bus departures (HAFAS & WienerLinien), and provides a live "Leave Status" based on real-time delays.

Platform Next.js React Native TypeScript

🚀 How It Works

  1. Sync Your Calendar: Import your .ics file or provide a calendar URL. The app extracts your upcoming events and destinations.
  2. Set Your Origin: Define your home station or let the app use your current geolocation.
  3. Journey Calculation: The app queries the HAFAS protocol and WienerLinien APIs to find the best public transport connections to your event destination.
  4. Real-Time Monitoring: It monitors your train's real-time departure time, accounts for delays, and adds your local travel time (e.g., biking to the station) to calculate a dynamic countdown.
  5. Leave Status: You get a clear status: Leave now, On time, Delayed +X min, or Departure missed.

🧱 Project Structure

This project uses a monorepo setup (npm workspaces) to manage multiple, interconnected parts:

Directory Description
apps/web/ The main web dashboard built with Next.js 16, React 19, and Tailwind CSS 4.
apps/mobile/ The on-the-go mobile client built with React Native 0.81 and Expo 54.
packages/core/ Shared domain logic, types (Event, Journey, Station), countdown utilities, and status calculators.
packages/api-client/ A lightweight client that handles API proxies for HAFAS requests, calendar parsing, geocoding, and bike routing.

🛠 Development & Running the Application

Prerequisites

  • Node.js (version 20.x or higher)
  • npm (version 9.x or higher)

Installation

  1. Clone the repository:

    git clone <repository-url>
    cd TimeToLeave
    
  2. Install dependencies:

    npm install
    
  3. Environment variables:

    • For apps/web and apps/mobile, copy .env.example to .env in each app directory and update the backend API URL and any required keys.

Available Scripts

Script Command Description
dev npm run dev Starts the Next.js development server for the Web dashboard.
dev:mobile npm run dev:mobile Starts the Expo development server for the Mobile client.
build npm run build Builds the production bundle for the Web application.
test npm run test Runs Vitest for the Web app and Jest for the Mobile app.
lint npm run lint Runs ESLint across both web and mobile clients.
typecheck npm run typecheck Runs TypeScript type checking across all workspaces.

📝 Key Features & Tech Stack

Web Application (apps/web)

  • Framework: Next.js 16.2.6 (App Router)
  • UI: React 19.2.4 with Tailwind CSS 4
  • State Management: React Context (via EventsProvider and ReminderSettingsProvider)
  • Routing: Next.js built-in routing for / (event list) and /calendar views.

Mobile Application (apps/mobile)

  • Framework: React Native 0.81 via Expo 54
  • Navigation: React Navigation 7 (Native Stack)
  • Device APIs:
    • expo-location: For geocoding your current position.
    • expo-calendar: For native calendar event integration.
    • expo-notifications: For native push notifications when it's time to leave.
    • @react-native-async-storage/async-storage: For persisting settings and local state.

Core Logic (packages/core)

  • Countdown Utilities: Calculates time-deltas and assigns color codes (Red/Orange/Yellow/Green/Blue) based on urgency.
  • HAFAS Time Parsing: Highly accurate timezone-aware parsing for HAFAS timestamps, specifically handling Europe/Vienna (CET/CEST) and DST transitions.
  • WienerLinien Support: Native types and handling for Vienna public transport departures.
  • Leave Status: Derives human-readable statuses (Leave now, Delayed +10 min, etc.) by comparing the best non-cancelled journey's real departure time against the current time.

📄 API Client Usage

The @timetoleave/api-client package provides a clean interface to interact with your backend proxy, which handles the heavy lifting of HAFAS protocol communication and calendar parsing.

import { ApiClient } from "@timetoleave/api-client";

// Initialize with your backend URL
const api = new ApiClient("http://localhost:3000");

// 1. Sync your calendar
const events = await api.fetchCalendar("https://example.com/calendar.ics", 7);

// 2. Search for a station via the HAFAS LocMatch endpoint
const stationResult = await api.hafasRequest({
  svcReqL: [
    {
      meth: "LocMatch",
      req: { searchTxt: "Wien Mitte", maxMatches: 5 },
    },
  ],
});
const stations = stationResult?.svcReqL?.[0]?.res?.locL ?? [];

// 3. Find journeys between stations for a specific date
const journeys = await api.searchJourneys(
  stations[0].extId, // From
  "dest:extId",      // To
  new Date()         // Date
);

// 4. Get a bike route from your current location to the station
const bikeRoute = await api.getBikeRoute(
  48.2082, 16.3738,  // From lat/lng
  48.1850, 16.3780   // To lat/lng
);

🛡️ Testing & Quality Assurance

The project provides comprehensive scripts for maintaining code quality:

  • Linting: Use npm run lint to catch stylistic and structural errors via ESLint 9.
  • Type Checking: Use npm run typecheck to ensure strict type safety across the codebase via TypeScript 5.
  • Testing:
    • The web application uses Vitest (v4.1.5) with jsdom and @testing-library/react.
    • The mobile application uses Jest (v29.7.0) with jest-expo and react-test-renderer.

📂 File Structure

├── apps/
│   ├── mobile/         # Mobile application using React Native and Expo
│   └── web/             # Web application using Next.js and Tailwind CSS
├── packages/
│   ├── api-client/     # API client for HAFAS, Calendar, and Routing proxies
│   └── core/            # Shared domain types, countdowns, and HAFAS time utilities
├── node_modules/       # Third-party dependencies
└── README.md           # The file you're reading now

Built for developers who bike to the train and hate missing their connections.

S
Description
No description provided
Readme 35 MiB
Languages
TypeScript 96.5%
JavaScript 1.1%
Kotlin 0.7%
CSS 0.7%
Ruby 0.4%
Other 0.6%