Skip to content

Search Interrail trains across Europe in the browser - #102

Open
davd-gzl wants to merge 4 commits into
interrail-feesfrom
interrail-europe
Open

davd-gzl wants to merge 4 commits into
interrail-feesfrom
interrail-europe

Conversation

@davd-gzl

@davd-gzl davd-gzl commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

Before: on Interrail, Railmap searched SNCF's trains only. Paris to Madrid, Amsterdam or Zurich found nothing past the border, and #101 added Renfe by hand.

After: on Interrail, Railmap searches every operator train-api publishes, on the device. An exact trip (one way, round trip, flexible days) finds journeys that change between operators, such as Paris to Madrid with a TGV to Barcelona and then an AVE. Explore from a station lists the towns reachable across Europe. Every station these operators serve is in the station fields and on the map. A Renfe, DB or NS train books on that operator's site ("Book on Renfe") and carries no reservation fee.

It scales by downloading only what a search needs. On a visit the app loads every operator's station list, which is small. Each search then loads only the timetables of the operators on the way: Paris to Madrid loads SNCF and Renfe, never Finland. Settings gains an opt-in "Europe's timetables offline" switch that keeps every country on the device and searches from that copy when there is no connection.

This replaces #101, so #101 can be closed. It needs train-api #14 and #15 merged and deployed. Until /v2/ is published, or whenever it can't be reached and no offline copy is kept, Interrail searches SNCF's trains alone, exactly as before.

How:

  • src/europe/engine.ts is a copy of train-api's src/search.ts, with no imports. It matches stations across operators by position and name, groups them into towns, and runs a connection scan.
  • src/europe/network.ts builds the station directory from every operator's stations.json.
    • Station ids. A place SNCF serves keeps SNCF's id. Any other place takes the directory's id (amsterdam-centraal). SNCF's stations get their positions from the app's own station list.
    • Picking operators. operatorsFor picks the operators a search needs. Two operators count as linked when they serve the same town. A trip uses every operator on a shortest chain of linked operators between its two towns, or on a chain one operator longer. Explore uses the origin's operators and their neighbours.
    • Search networks. A search network is built over those operators' bundles alone. The last two are kept, so a calendar reuses one.
  • src/europe/europe.worker.ts and client.ts load the files and answer searches. Searches the user just asked for go ahead of background work.
    • The days on screen are searched before the first paint.
    • The rest of the bookable days are searched afterwards, and the calendars then fill in.
  • Offline mode. Every train-api file goes to Cache Storage (railmap-europe) and is read from there when the network fails. A sync on each visit re-downloads only when train-api's index is newer. Turning it off deletes the copy. public/sw.js leaves that cache alone and no longer caches /v2/ files itself. The cache name is bumped so the new service worker installs.
  • findJourneys reads the cached journeys first, through setJourneySource. The trip list, the calendars and the round-trip return lists use them without other changes. A route the network doesn't serve falls back to SNCF's trains.
  • Explore keeps SNCF's direct destinations. It then adds the 80 fastest of the 150 busiest towns reachable that day.
  • Ideas, arrive-at, multi-city and the planner still search SNCF's trains.
  • Booking per operator is ported from Add Spain's Renfe trains to Interrail #101. Operator names are in src/data/operators.ts, and booking sites come from train-api's index.

Tests:

  • tests/europe.test.ts covers:
    • station matching, cross-operator journeys and town search;
    • operator picking, and the directory working before any timetable loads;
    • explore ranking and the leg conversion;
    • the findJourneys source, operators and the registry.
  • Two browser scenarios run against a stand-in train-api with SNCF, Renfe and Finland's VR:
    • Paris to Madrid goes via Barcelona and the calendar fills in. Finland's timetable is never downloaded. Explore reaches Madrid.
    • The offline switch keeps all three countries' timetables, and a search still finds Paris to Madrid with train-api down.
  • npm test (253 tests), build, prerender, generate-pages, verify and test:e2e (27/27) pass locally.

On Interrail, the page downloads every operator's trip bundle from train-api
(/v2/) into a worker and searches them with train-api's journey engine. The
exact trip (one way, round trip, flexible days) and explore from a station
read its results; a train of another operator books on that operator's site.
When the bundles can't load, Interrail searches SNCF's trains alone.
…request

The Europe worker now downloads every operator's station list for the directory and,
per search, only the trip bundles of the operators on the way. Settings gains an
opt-in offline mode that keeps every operator's files in Cache Storage and searches
from them when train-api can't be reached.
Same change as train-api's engine: Munich's place no longer takes the name of
the tram stop "Hauptbahnhof (U, Tram)".

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant