initial commit

This commit is contained in:
2026-05-09 09:30:52 +02:00
commit 8e02656431
7367 changed files with 732863 additions and 0 deletions
+125
View File
@@ -0,0 +1,125 @@
# ÖBB Train Planner
Checks the ÖBB real-time schedule, picks the best train for your upcoming calendar events, and shows a live "leave by" countdown from your current location.
## What's included
```
oebb-planner/
├── server/
│ ├── index.js ← Node.js proxy server (ÖBB API + ICS parser)
│ └── package.json
├── oebb-planner.jsx ← React front-end (use in Claude.ai artifacts or any React app)
└── README.md
```
---
## Quick start
### 1 — Start the proxy server
The server bypasses ÖBB's CORS restrictions and parses ICS calendar files.
```bash
cd server
npm install
npm start
# → ÖBB Planner API running on http://localhost:3001
```
> **Requires Node.js ≥ 18** (uses built-in `fetch` and `AbortSignal.timeout`).
> For development with auto-reload: `npm run dev`
### 2 — Open the React app
Paste `oebb-planner.jsx` into a Claude.ai artifact (or your own React app).
The app detects whether the server is online and shows a status indicator in the header.
---
## Calendar integration
The app reads any standard ICS calendar. Only events that have a **location field** and fall within the **next 14 days** are imported.
### Option A — ICS URL (Google Calendar, Outlook, Fastmail…)
1. In the app, open the **Calendar** panel → **ICS URL** tab
2. Paste your calendar's secret ICS address
**Google Calendar:**
Settings → click your calendar → scroll to *"Secret address in iCal format"* → copy the URL
**Apple Calendar (iCloud):**
Calendar app → right-click calendar → "Share Calendar" → enable public calendar → copy the URL
(change `webcal://` to `https://` or paste as-is — the server handles both)
**Outlook:**
Settings → View all Outlook settings → Calendar → Shared calendars → Publish → ICS link
### Option B — Upload .ics file
Export your calendar as a `.ics` file from any app (File → Export in Apple Calendar, etc.) and upload it via the **Upload File** tab.
---
## How the train matching works
1. Your **current GPS location** is used to find the nearest ÖBB station (via the HAFAS `LocGeoPos` API).
2. Each event's **location field** is used to search for the nearest destination station (`LocMatch`).
3. The HAFAS `TripSearch` endpoint finds journeys departing up to 2 hours before your event.
4. The **"leave by" time** = next catchable train departure 12 minutes (default walk time to station).
5. Data refreshes automatically every **60 seconds**.
---
## Server endpoints
| Method | Path | Description |
|--------|------|-------------|
| `POST` | `/api/hafas` | Proxy to `fahrplan.oebb.at/bin/mgate.exe` |
| `GET` | `/api/calendar?url=<ics_url>` | Fetch & parse a remote ICS calendar |
| `POST` | `/api/calendar/parse` | Parse raw ICS content sent in request body |
| `GET` | `/api/health` | Liveness check |
---
## Customisation
| Variable | Location | Default | Description |
|----------|----------|---------|-------------|
| `WALK_MINS` | `oebb-planner.jsx` | `12` | Walk time from your location to origin station |
| `PORT` | `server/index.js` | `3001` | Server port |
| `horizonDays` | `server/index.js` | `14` | How far ahead to look for calendar events |
| `PROXY` | `oebb-planner.jsx` | `http://localhost:3001` | Server URL |
---
## Deploying beyond localhost
To run this on a server or share it with others:
1. Set `PORT` via environment variable: `PORT=8080 npm start`
2. Update `PROXY` in `oebb-planner.jsx` to your server's URL
3. Restrict CORS in `server/index.js` if needed:
```js
app.use(cors({ origin: "https://your-app.example.com" }));
```
---
## Troubleshooting
**"Server offline" shown in the app**
→ Make sure `npm start` is running in the `server/` directory.
**No trains found for an event**
→ Check that the destination in your calendar event is a recognisable ÖBB station name
(e.g. "Graz Hbf", "Salzburg Hauptbahnhof"). Verbose postal addresses are trimmed automatically.
**Calendar import returns 0 events**
→ Only events with a `LOCATION` field set are imported. Make sure your events have a location
and fall within the next 14 days.
**ÖBB returns errors**
→ The HAFAS API occasionally changes. Check `fahrplan.oebb.at` is reachable from your server.