A minimalist NYC subway, bus, and PATH schedule viewer written in React.
This project relies on Transiter for fetching data. After running Transiter locally or hosting it, set the TRANSITER_URL
environment variable (it is recommended to use a .env.local
file) to the base URL of the HTTP endpoint:
TRANSITER_URL="http://localhost:8080"
By default, it is assumed that the NYC Subway (us-ny-subway
) is installed in your Transiter instance. The UI also supports the NYC Bus system (us-ny-nycbus
) and the NYC/NJ PATH train (us-ny-path
). If you wish to enable other systems, you can set the below environment variable with a comma separated list of system IDs. Note that if you wish to remove the NYC subway, you should also change the root path redirect set in next.config.js to point to the path of an installed system.
In addition to systems in Transiter, you can also enable CitiBike station information by adding the us-ny-nyccitibike
system. See more details in the CitiBike Station Information section.
NEXT_PUBLIC_ENABLED_SYSTEMS="us-ny-subway,us-ny-nycbus,us-ny-path"
Transiter uses gRPC protobuf definitions for it's API. TypeScript types can be generated from this, which are then used to annotate the data returned from Transiter. To generate new types:
- Install the Buf CLI
- Copy the newest
public.proto
file from Transiter toproto/transiter/
- From the
proto/
directory, runbuf generate
The above only needs to be done if the API definition changes, since generated files are checked in.
The maximum range (in KM) to fetch stops for each system can be configured with the below environment variables:
# Default max stop distance if not specified for a system
NEXT_PUBLIC_MAX_STOP_DISTANCE_KM=3.2
# Max distance for NYC Subway stops
NEXT_PUBLIC_US_NY_SUBWAY_MAX_STOP_DISTANCE_KM=3.2
# Max distance for NYC Bus stops
NEXT_PUBLIC_US_NY_NYCBUS_MAX_STOP_DISTANCE_KM=1.6
# Max distance for PATH stops
NEXT_PUBLIC_US_NY_PATH_MAX_STOP_DISTANCE_KM=10.0
Additionally, since the NYC bus system is very dense, the max number of stops returned can also be limited using:
NEXT_PUBLIC_US_NY_BUSES_MAX_STOPS=30
CitiBike station information can also be displayed. This relies on the public GBFS feed provided by Lyft and does not require any additional configuration once the system is enabled.
There are several environment variables that can be set to customize how this page behaves, though these all have sensible defaults it not specified:
# The URL of the CitiBike GBFS feed
NEXT_PUBLIC_CITIBIKE_GBFS_URL="https://gbfs.citibikenyc.com/gbfs/2.3/gbfs.json";
# The maximum distance (in KM) that a returned station will be from the user
NEXT_PUBLIC_CITIBIKE_MAX_STATION_DISTANCE_KM=3.2,
# The maximum number of nearby stations that will be returned
NEXT_PUBLIC_CITIBIKE_MAX_RESULTS=100
# The minimum number of stations with at least 1 classic bike that will be returned. This is still subject to the max results and max distance
# parameters defined above, so there can be cases where fewer stations are returned.
NEXT_PUBLIC_CITIBIKE_MIN_STATIONS_WITH_CLASSIC_BIKES=10,
# The minimum number of stations with at least 1 e-bike that will be returned. This is still subject to the max results and max distance
# parameters defined above, so there can be cases where fewer stations are returned.
NEXT_PUBLIC_CITIBIKE_MIN_STATIONS_WITH_EBIKES=10,
# The minimum number of stations with at least 1 open dock that will be returned. This is still subject to the max results and max distance
# parameters defined above, so there can be cases where fewer stations are returned.
NEXT_PUBLIC_CITIBIKE_MIN_STATIONS_WITH_SPACES=10
To enable the chat feature, set the below environment variable:
NEXT_PUBLIC_CHAT_ENABLED="true"
In addition to Transiter, the chat feature requires an OpenAI API key and a Google Maps API key:
# Google maps API credentials
OPENAI_API_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
GOOGLE_MAPS_API_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Since the APIs used by the chat feature can be expensive, rate limiting can optionally be enabled:
ENABLE_RATE_LIMITING="true"
If it is enabled, a Redis URL and access token from Upstash are also required:
# Redis credentials
UPSTASH_REDIS_REST_URL="https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
UPSTASH_REDIS_REST_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Finally, global daily and per-ip/per-minute rate limits can be configured:
# Daily and per IP address limits
DAILY_API_LIMIT=1000
PER_IP_PER_MIN_LIMIT=5
npm install
npm run dev
- Usage of the MTA's subway icons and other intellectual property has been granted through their licensing program.
- Subway icons are directly from or based on this project: https://github.com/louh/mta-subway-bullets