Welcome to BusRate NYC! This is an app designed to help provide insights about bus performance in the New York City MTA bus system.
- Being a frequent bus commuter, the importance of consistent and reliable bus service became really apparent to me
- To reduce reliance on cars and increase transit ridership, transit systems must be improved.
- To increase bus ridership, the reliability of the bus system must get better.
- Reliable bus service means having headways (wait times between buses) that are both short and consistent.
- Before something can get better, it has to be measured.
- The MTA is great about providing real time bus data for all of its vehicles. ("How far away is the bus now?") It offers a free API that conforms to the GTFS specification.
- However, as far as I could tell, the MTA doesn't offer any historical departure data. So you can't answer questions like "How long ago did the bus depart?" "How well does this bus adhere to its schedule?" "How decent are the actual wait times?"
- BusRate NYC provides historical departure data so that all of those questions can be answered.
(For more technical details, see the README for BusRate API)
- Every 30 seconds, BusRate calls the MTA BusTime API and gets the locations of every vehicle in the system. For each vehicle, this data includes a stop reference (which bus stop) and an arrival text ("approaching", "at stop", "< 1 stop away", etc.)
- The vehicle locations are persisted to a database using the BusRate API, which runs on Rails and Postgres.
- Every minute, the BusRate API compares all of the vehicle locations less than 4 minutes old.
- If two vehicle locations look like a departure (e.g. the bus goes from "at stop" to "approaching" the next stop), a historical departure is recorded in the BusRate API database.
- Approximately 800 historical departures are created every minute.
If you don't want to run the app locally, there is a live demo available at http://busrate.herokuapp.com. *(Please see the note below about HTTPS)
- Clone the repo locally
- At a Terminal, run
yarn install
yarn start
should start the app at http://localhost:3000
Please note: Because this is a demo, the back end API currently doesn't support HTTPS. If no search results show when you start typing, make sure you run the app with http://
at the beginning of the URL and not https://
. I don't consider this a major issue because this app deals only with publicly available information, and does not collect any data from users.
Constants: Since the BusRate API handles communication with MTA BusTime, you don't need an API key to run this front-end React app. The BusRate API address is hard-coded in constants.js
. If you're running the API locally, you'll need to change that reference to localhost:5000
(or whatever port you run Rails server on).
- Start typing the name of your favorite NYC bus route. For example,
M60
for the M60 Select Bus Service to LaGuardia Airport. - Click or tap the bus route you want. You'll see the two terminals (directions the bus can go in) along with a list of stops. Click the direction and stop you're interested in.
- You'll see a page with three sections:
- Expected departure - real time data for the next vehicle departure from that stop.
- Historical departures - The last 8 departures for that bus line are listed on a graph, along with previous departures. For weekdays, the previous departures will be for the same time the previous business day. For weekends, previous departures will be listed for the same time period a week ago.
- If other bus lines also depart from the same bus stop, they will be filtered out and not shown. The departures you see will be only for the selected bus line.
- Realtime data will automatically update from the BusTime API every 9 seconds.
- Historical data will automatically update every 60 seconds.
- If you lose your connection and BusRate isn't able to update data, you'll see a small red dot in the upper right corner of the section with stale data. This dot will disappear once updated data is received.
- Once a bus departs, BusRate will immediately show the departure as a white dot. Once the API actually creates the departure in the database, it will turn from white to yellow -- this should happen within the next 2 minutes or so.
- If a driver skips over a stop, or the back end has momentary problems, the departure may not be recorded properly. Every so often, the system checks for missing departures. If a vehicle has recorded departures at both a previous and subsequent stop on the route, the system will insert "interpolated" departures. (These dots will be grey.)
- If you hover your mouse over a departure dot, you can see useful data about that particular departure: time, vehicle number, headway (wait time since the last departure), and whether the departure is interpolated, etc.
- BusRate Score - A score on a 0-100 scale, where 0 is Abysmal and 100 is Excellent. Also shows several other stats that make up the score, including average wait time, consistency, and bus bunching info. By default, the score is for the 8 recent departures displayed on screen. Click on the score itself to cycle through scores for previous departures, weekdays, weekends, rush hours, and all-time score for this particular stop.
Now that we have historical departure data, there's a ton of interesting stuff that can be done with it. I may work on one or more of these in the future:
- * Bus bunching data (both real-time and historical)
- Historical trip duration from stop to stop
- Average headways for this bus line - overall; for certain time periods; per hour; etc.
- Schedule adherence / comparison
- Generate a "score" for each bus based on consistency and low headways
- Machine learning predictions of future headways
- Rate the accuracy of realtime data by comparing it to when the bus actually arrived
- If you have more ideas, please feel free to share! (@jeremy646 on Twitter)
- Custom CSS; no frameworks used
styled-components
library is used to style each React component- CSS Grid is used in
index.css
to describe the basic layout of the app - CSS Flexbox is used in
DepartureGraph.js
to make the visual departure graphs; also in Ratings details - Keyframes are used in
Loader.js
which is a basic CSS loader/spinner - Media queries are used to provide a fully responsive design
- Redux is used to keep track of most app state, using the principles outlined in Nir Kaufman's Thinking In Redux.
- Instead of using Thunk or redux-sagas, I wrote custom middleware (
middleware/core/api.js
) to make API calls. I found this to be much simpler and cleaner than you may think! - Continuing the ideas of Thinking In Redux, I also wrote custom middleware (
middleware/core/normalize.js
) to transform the deeply nested GTFS data from the MTA BusTime API into a much more manageable data shape. - Feature middleware takes care of more side effects, including purging unneeded data and hiding the loading spinner.
- The state of API requests is kept in the Redux store as a Set; see this blog post for more info
- create-react-app
- Moment.js
- React Router
- react-search-input