Inspiration
The ETA Spot app for Bloomington Transit has a 1.8-star rating on the Play Store. Reading through the reviews, the complaints are the same thing repeated over and over: favourites disappear after closing the app, arrival times seem made up, and the UI looks like it hasn't been touched since 2012. We ride BT buses to campus every day. We had opinions.
What it does
BT Transit shows you the next bus at your stop in real time. You pin routes to the home screen and it finds the nearest stop that actually serves that route, which sounds obvious but the old app got this wrong and it was the thing people complained about most. The map shows live bus positions updating every 10 seconds, with stop markers for every stop along whichever route you select. There is an AI trip planner where you type where you want to go and it figures out which buses to take, including walking directions and a transfer if needed. It also calculates whether you can physically walk to a stop in time for the next bus, using your real walking time from Google Directions, not just straight-line distance.
How we built it
Kotlin and Jetpack Compose for the UI, Clean Architecture with MVVM so each layer has one job, Hilt for dependency injection, Room for the GTFS static schedule data, DataStore for anything that needs to survive an app restart. Live bus positions and arrival predictions come from GTFS Realtime protobuf feeds polled every 10 seconds. The AI backend is a FastAPI service deployed on Railway that takes a natural language trip request and returns a structured plan. We built the whole thing in about 24 hours split across four people.
Challenges we ran into
GTFS time strings can go past midnight in a way most people would not expect. "25:30:00" is a real valid value for a trip that runs after midnight, and we hit that bug at 2am, which is either poetic or just cruel. Merging three branches with conflicting Gradle dependency configs ate a few hours too. The trickiest product problem was the route pin logic: the naive approach finds the globally nearest bus stop and then filters arrivals to your route, which means if that stop does not serve Route 9, Route 9 shows no buses. The fix is to find the nearest stop among stops that actually serve the pinned route, which is a small change in code and a big change in whether the feature works.
Accomplishments that we are proud of
The walking reachability feature came out better than we expected. You tap any stop on the map and the app tells you whether you can make it on foot before the next bus leaves, draws the actual walking route on the map, and shows your spare time down to the second. The multi-pin home screen also genuinely fixes the thing that drove the worst reviews of the old app.
What we learned
Building against real user complaints is faster than designing from scratch. Every hour we spent reading Play Store reviews saved us from building something nobody wanted. We also learned that protobuf parsing, Gson, and kotlinx serialization do not coexist gracefully in the same project if you are not careful about which Retrofit converter factory goes where.
What's next for BT Transit App
A home screen widget that shows your next bus without opening the app. Background notifications when a tracked bus is two stops away. Offline schedule access so the app still works when the backend is unreachable. We also want to replace the full GTFS static re-download with incremental updates so the schedule data stays current without parsing the entire zip file every 24 hours.
Built With
- android-studio
- fastapi
- kotlin
Log in or sign up for Devpost to join the conversation.