diff --git a/.github/workflows/update-data.yml b/.github/workflows/update-data.yml index 555b045..071215f 100644 --- a/.github/workflows/update-data.yml +++ b/.github/workflows/update-data.yml @@ -37,7 +37,7 @@ jobs: run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - git add public/data/tgvmax.json public/data/meta.json + git add public/data/tgvmax.json public/data/meta.json public/data/interrail.json public/data/interrail-meta.json if git diff --cached --quiet; then echo "No changes to commit." else diff --git a/README.md b/README.md index d1977cc..e4219d8 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,13 @@ It also handles connections (up to 6 changes, an optional stopover city, overnig ## Supported passes -| Pass | Status | What Railmap shows | +| Pass | Who can use it | How it works | | --- | --- | --- | -| MAX JEUNE (16 to 27) | Available | Trains with a free MAX seat open for booking | -| MAX SENIOR (60+) | Available | Trains with a free MAX seat open for booking | -| Interrail | In progress ([#83](https://github.com/offware-apps/Railmap/pull/83)) | Every SNCF train a pass holder can take, international stops included | +| **[MAX JEUNE](https://www.sncf-connect.com/catalogue/description/max-jeune)** | 16 to 27, €79/month, 12-month minimum | €0 seats in 2nd class on TGV INOUI, OUIGO high-speed and Intercités with reservation, in France plus Luxembourg and Freiburg. Book up to 30 days ahead, 6 trips at a time, one €0 trip a day from the same station, confirm 1 to 2 days before. No €0 seats on Friday and Sunday afternoons and evenings or holiday eves. Railmap shows the trains with a free MAX seat open for booking. | +| **[MAX SENIOR](https://www.sncf-connect.com/catalogue/description/max-senior)** | 60 and over, same price | Same €0 seats as MAX JEUNE. | +| **[Interrail](https://www.interrail.com/en/interrail-passes/global-pass)** | Residents of the 33 Interrail countries (everyone else buys Eurail). Youth up to 27, senior from 60, children 4 to 11 free with a Child Pass | Any train with a pass-holder reservation (€10 to 20 on TGV, limited seats). Living in France: a Global Pass covers only one trip out of France and one trip back in, and there is no One Country Pass for your own country. Railmap shows every SNCF train a pass holder can take, international stops included. | + +**Lower carbon.** A TGV trip emits about 50 times less CO₂ than driving alone and 100 times less than flying ([ADEME](https://impactco2.fr/outils/transport)). Each exact trip shows its own figure. Booking always happens on [SNCF Connect](https://www.sncf-connect.com/). Railmap is an independent project, not affiliated with SNCF, and does not sell tickets. Availability is refreshed about once a day, so confirm before you book. @@ -101,9 +103,10 @@ specs/ guiding principles SNCF publishes which trains have a free MAX seat as open data. Railmap is a static site on top of it: -1. A scheduled GitHub Action downloads the dataset each morning and keeps only the trains with a free seat (about 77 MB trimmed to about 6 MB). -2. Your browser downloads that file and runs every search on your device. It can query the SNCF API directly as a fallback. -3. Everything is served as static files from GitHub Pages. There is no backend, no database and no server cost. +1. [train-api](https://github.com/offware-apps/train-api) publishes each pass's timetable every morning as static JSON. The app reads it first. +2. A scheduled GitHub Action also snapshots the dataset into the app itself (about 77 MB trimmed to about 6 MB), which the app falls back to when train-api is unreachable or out of date. +3. Your browser downloads the timetable and runs every search on your device. +4. Everything is served as static files from GitHub Pages. There is no backend, no database and no server cost. More detail: diff --git a/docs/user-flows.md b/docs/user-flows.md index a46faae..5f43767 100644 --- a/docs/user-flows.md +++ b/docs/user-flows.md @@ -214,6 +214,30 @@ the destination is reachable, with its calendar open. from any screen. (The two overlap — a known cleanup item.) A saved trip opens its ticket modal, whose "See all dates" opens the route page; a favorite prefills the Trip tab with that route alone. +- **Pass** — the header's pass picker: **MAX JEUNE** (default), **MAX SENIOR**, or + **Interrail**. Timetables come from [train-api](https://github.com/offware-apps/train-api) + first (`` in `index.html`, refreshed daily), and from the bundled + snapshots when it is off, unreachable, more than 36 hours old or entirely in the past (a + stale train-api copy still beats the sample offline; the service worker keeps the last + one). Both MAX passes search the MAX JEUNE + timetable (trains with a free MAX seat; `tgvmax.json` as fallback). Interrail searches + every train in the SNCF feed (`interrail.json` as fallback, see `src/data/compact.ts`): + each one takes a pass-holder reservation, international stops included. No open data says whether an Interrail seat is left, so every Interrail result + page opens with a notice saying so, and copy that would claim a free MAX seat reads its + `_ir` variant instead ("green = at least one train"). Switching between a MAX pass + and Interrail loads the other timetable while the page stays up (the results dim under a + "Loading…" pill), then re-runs the search; each timetable loads once per visit, so switching + back is instant. Switching between the two MAX passes re-runs straight away. Booking still opens SNCF Connect, + where pass-holder reservations are sold; "How does it work?" links Interrail's page on + French reservations. A `card=interrail` link loads the Interrail snapshot at boot. + "How does it work?" lists who can use each pass and its rules (MAX JEUNE 16 to 27, + MAX SENIOR from 60, booking window and daily limits; Interrail for residents of the 33 + countries, Eurail for everyone else) and the special case for people living in France (a + Global Pass covers one trip out and one trip back in), with links to the official pages. + The Interrail seat notice on results ends with that France residence rule. An exact + trip (Trip tab, origin and destination) shows one line comparing the trip's CO₂ by train + with driving alone and flying, from ADEME factors over the straight-line distance + (`src/util/eco.ts`). - **Settings** — theme, MAX Jeune/Senior, comfortable/compact, and Low-end mode (map off + reduced motion + compact) with a one-time nudge on weak devices; language. - **Mobile** — the form is a sheet that collapses to a search bar (a long route wraps it to diff --git a/index.html b/index.html index 94252c4..5a6e2b3 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,7 @@ Trains MAX JEUNE / MAX SENIOR (ex-TGVmax) réservables — Railmap + + -