Files
2026-05-18 15:01:53 +02:00

5.2 KiB

Development Guide

Prerequisites

  • Node.js 20 or newer
  • npm 9 or newer
  • Android Studio or Xcode for native mobile builds
  • Expo/EAS tooling when building or submitting mobile apps

Install

npm install
cp .env.example .env

The root workspace owns dependency installation. Avoid installing separately inside workspaces unless you are intentionally changing that workspace's dependency list.

Environment

Variable Default Purpose
PORT 3000 through Next dev defaults Web server port when the runtime honors it.
HAFAS_URL https://fahrplan.oebb.at/bin/mgate.exe ÖBB HAFAS endpoint.
HAFAS_TIMEOUT_MS 10000 HAFAS request timeout.
HAFAS_VER, HAFAS_LANG, HAFAS_AID, HAFAS_CLIENT_* ÖBB app-compatible defaults HAFAS request envelope metadata.
NOMINATIM_URL https://nominatim.openstreetmap.org Geocoding endpoint.
NOMINATIM_USER_AGENT TimeToLeave/2.0 Required Nominatim user agent.
OSRM_URL https://router.project-osrm.org Bike and foot routing base URL.
WIENER_LINIEN_API_URL https://api.wienerlinien.at/darwin-v2 Wiener Linien live data base URL.
OEBB_GTFS_URL ÖBB 2026 GTFS ZIP Optional HAFAS response enrichment source.
CORS_ALLOWED_ORIGINS http://localhost:3000 fallback Allowed browser origins for /api/*.
API_RATE_LIMIT_MAX_REQUESTS 120 Per-IP API requests per window.
API_RATE_LIMIT_WINDOW_MS 60000 Rate-limit window length.
DEPLOYMENT_URL local fallback in OAuth code Public app URL for Google OAuth redirects.
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URI none Enables Google Calendar sync.
APP_VERSION 0.1.0 Version returned by /api/health.
EXPO_PUBLIC_API_BASE_URL empty Mobile backend URL. Required for physical devices unless the empty base URL is intentionally proxied.

Commands

Command Description
npm run dev Start the web app with next dev.
npm run build Build the web app.
npm run start Start the built web app.
npm run dev:mobile Start the Expo dev server.
npm run android Run the Expo app on Android from the root script.
npm run ios Run the Expo app on iOS from the root script.
npm run lint Run ESLint across web, mobile, core, and api-client.
npm run typecheck Run TypeScript checks across all workspaces.
npm run test Run web Vitest tests and mobile Jest tests.

Workspace-specific examples:

npm run test -w apps/web
npm run test -w apps/mobile
npm run typecheck -w packages/core
npm run typecheck -w packages/api-client

Web Routes

Route Description
/ Departure desk with next upcoming event, train/bike mode selector, live journeys, route sections, reminders, and nearby Wiener Linien departures.
/calendar Calendar import/management with URL, file, Google OAuth, and batch destination editing.

The web add/edit event flow is implemented by apps/web/src/app/add-event/AddEventModal.tsx, not a standalone route.

API Routes

Endpoint Methods Notes
/api/health GET Returns { ok, ts, version }.
/api/hafas GET, POST GET is a simple trip search. POST validates and forwards TripSearch or LocMatch.
/api/geocode GET Requires name; optional countrycodes. Returns the first result.
/api/bike-route GET Requires fromLat, fromLng, toLat, toLng.
/api/walk-route GET Same coordinate contract as bike route, using OSRM foot profile.
/api/calendar GET Requires an allowed remote ICS url; optional days.
/api/calendar/parse POST Parses raw ICS text from the request body.
/api/calendar/google GET Requires Google OAuth token cookie; optional day horizon.
/api/auth/google GET Starts OAuth.
/api/auth/google/callback GET Completes OAuth.
/api/auth/google/status GET Reports configuration and connection state.
/api/auth/google/disconnect POST Clears OAuth token cookie.
/api/wienerlinien/stops GET Requires lat, lng; optional radius, capped server-side.
/api/wienerlinien/monitor GET Accepts repeated stopIds, capped server-side.

Docker

The web app includes Docker support:

cd apps/web
docker-compose up --build

Testing Notes

  • Web tests use Vitest, jsdom, and Testing Library.
  • Mobile tests use Jest, jest-expo, and React Native Testing Library.
  • Route, geocoding, HAFAS, calendar, routing, reminder, and UI component tests are present across the repo.
  • Run npm run typecheck after changing shared types because both apps consume packages/core.

Development Rules

  • Use @timetoleave/core for shared behavior.
  • Use @timetoleave/api-client for client-to-backend calls that are shared by web and mobile.
  • Keep backend validation close to route handlers, then delegate external service behavior to apps/web/src/lib.
  • Never parse HAFAS date/time values with ad hoc Date logic; use parseHafasTime() and hafasDateTime().
  • This repo uses Next.js 16. Read the relevant node_modules/next/dist/docs/ material before changing Next.js framework code.