GTFS Schedule¶
Renders GTFS schedule data as a timetable people can read: stops down the side, trips across, times in the cells.
It runs against a GTFS Core install on the same site, or against a remote one over its REST API. The remote mode exists because the public website and the data importer are often separate builds on separate release cycles.
What it does¶
- A timetable page per route, at a URL pattern you control.
- Timepoints only by default, with the full stop list available, so a long route does not produce an unreadable wall of numbers.
- Holidays and special dates offered by name — "Labor Day" rather than the 7th — whichever way the feed states them: as a service of their own, or as a date added to a service that already runs weekly.
- Manual stop ordering for routes where the feed's own sequence does not match how riders read the line.
- Stop headings link through to stop pages, so a timetable is a way into the rest of the site rather than a dead end.
- Your own wording for a route with no service, your own time format, and route naming by ID or by name.
Requirements¶
Drupal 10.3 or 11.
In local mode, GTFS Core 3.x on the same site. In remote mode, network access to a GTFS Core REST API — this module has no hard dependency on GTFS Core, so a front-end-only site can install it alone.
Installation¶
composer require drupal/gtfs_schedule
Configuration¶
Administration › GTFS › Schedule settings (/admin/gtfs/schedule/settings).
| Setting | Default | Notes |
|---|---|---|
| Use local | on | Off switches to a remote GTFS API |
| Endpoint base URL | empty | Remote mode only — the base of the other site's /gtfs/api/v2 |
| Feed alias | empty | Which feed to read |
| Agency ID | empty | Which agency within that feed |
| Base URL | /gtfs/routes/{route_id}/schedules |
The timetable URL pattern |
| Route name type | route_id |
Or name the route by its long or short name |
| Time format | site default | PHP date format for cells |
| Timepoints only | on | Show only published timing points |
| Days of upcoming dates to offer | 14 | How far ahead holiday and special dates are offered; 0 offers every date the feed carries |
| How to label a dated schedule | Both | name, date, or both — a date no calendar names is labelled by its date either way |
| Empty placeholder | empty | What to print in a cell with no time |
| No schedule message | empty | What to show for a route with no service |
| Schedule data lifetime | 3600 | Seconds a response may be reused; 0 fetches every view |
| Request timeout | 30 | Seconds to wait for the GTFS server |
Caching¶
One timetable page asks the GTFS server several questions: the route, its service and direction combinations, a label for each of those, and the times themselves. Within a single render each question is asked once. Across renders, Schedule data lifetime decides whether the answers are kept — at the default hour, a route's timetable is fetched once and served from cache until it expires. Schedules change when a feed is re-imported, not by the minute, so hours are a reasonable setting; 0 turns the stored copy off and pays for the fan-out on every view.
Timetable pages carry their lifetime and a gtfs_schedule:api_response cache
tag, so a page cache in front of the site expires in step with the data, and
use Drupal\Core\Cache\Cache;
use Drupal\gtfs_schedule\GtfsApiClient;
Cache::invalidateTags([GtfsApiClient::CACHE_TAG]);
drops every stored response after a re-import without waiting for the lifetime.
Responses are only shared between visitors when nothing identifies who asked. In local mode the visitor's session cookie travels with the request so the API can apply this site's access checks, and those responses are held for that one render only.
Stop order overrides¶
When the feed's stop sequence does not read the way the line does, override it at
Administration › GTFS › Schedule › Schedule order override
(/admin/gtfs/schedule/schedule-order-override). An override applies to the timetable
only — it does not modify imported data, and because it is stored as configuration rather
than content, it survives re-imports.
The override screens are provided by GTFS Core, not by this module, so they are available in local mode only. In remote mode the timetable follows whatever order the remote API returns.
Issues¶
File issues and merge requests at https://www.drupal.org/project/issues/gtfs_schedule.
Related modules¶
- GTFS Core — the entities, the importer and the API everything else reads
- GTFS Realtime — trip updates, vehicle positions and service alerts
- GTFS Display — stop, route and system displays for public screens
- GTFS Display Map — route and stop geometry on a map
- GTFS Display Map RT — live vehicles, and an embeddable map
- GTFS 511 — feed provisioning from the 511 SF Bay API
- GTFS+ — the GTFS+ extension files
Maintainers¶
This project has been sponsored by: