Real-time train arrivals and smart commute planning for Boston's MBTA subway system.
🔗 Live Demo → mbtalive.vercel.app
MBTA Live is a cross-platform transit app that provides real-time train arrival predictions, schedule data, and intelligent commute planning for all MBTA subway lines (Red, Orange, Blue, Green, Mattapan). Built with Flutter to deliver full cross-platform support with arrivals tracking, commute planning and arrival notifications.
- Live Arrivals — Real-time predictions merged with schedule data, auto-refreshing every 30 seconds
- Smart Commute Planner — 4-step wizard to configure daily commutes with personalized leave-by notifications
- Nearest Station Detection — GPS-based location lookup across 100+ MBTA stations using optimized parallel API calls
- Direction Filtering — Filter arrivals by destination with horizontal scrollable chips
- Favorites — Save frequently used route + station combinations for quick access
- Commute Cards — Contextual home screen card showing your next commute with nearby train times and a countdown
- Onboarding Flow — 3-page onboarding with name personalization and notification setup
- Dark Mode — Full Material 3 theming with automatic light/dark mode support
| Layer | Technology |
|---|---|
| Framework | Flutter (Dart) |
| State Management | Provider (ChangeNotifier) |
| Networking | Dio — concurrent API calls with error handling and retry logic |
| API | MBTA V3 REST API (predictions, schedules, routes, stops) |
| Local Storage | SharedPreferences (favorites, commutes, user settings) |
| Location | Geolocator (GPS-based nearest station) |
| Deployment | Vercel (web), Android (APK), iOS-ready |
lib/
├── main.dart # App entry point, onboarding check, Provider setup
├── models/ # Data classes (TrainArrival, Commute, Favorite, etc.)
├── services/ # API layer, persistence, location, commute engine
│ ├── mbta_service.dart # All MBTA API calls with concurrent fetch + merge
│ ├── commute_manager.dart # Commute CRUD + user profile (SharedPreferences)
│ ├── commute_engine.dart # Leave-by time calculation, train selection logic
│ ├── location_manager.dart # GPS permissions + current position
│ └── user_settings.dart # Favorites + route/stop persistence
├── providers/
│ └── train_provider.dart # Main ViewModel — state, auto-refresh, rate limiting
├── screens/ # Full-screen views (arrivals, commutes, settings, etc.)
├── widgets/ # Reusable UI components (ArrivalRow, CommuteCard, etc.)
└── theme/ # MBTA brand colors + Material 3 theme config
- Concurrent fetch — Predictions and schedules are fetched in parallel via
Future.wait() - Smart merge — Predictions take priority; schedules fill gaps for trips without real-time data
- Direction extraction — Unique destinations are extracted from arrivals for the filter pills
- Auto-refresh — A 30-second timer reloads data, with rate limiting to prevent redundant calls
- Sibling stop IDs — Multi-platform stations (e.g., Green Line surface stops) query all child stop IDs for complete coverage
Optimized from 22+ sequential API calls down to 3 parallel requests:
GET /stops?filter[route_type]=0,1— All subway stops in one callGET /routes?filter[type]=0,1— All routes (fetched in parallel)GET /routes?filter[stop]={id}— Which route serves the nearest stop
- Flutter SDK 3.11+
- Dart 3.11+
git clone https://github.com/yourusername/mbtalive.git
cd mbtalive
flutter pub get
flutter runTo run on web:
flutter run -d edge # or chromeTo build for production:
flutter build web --release
flutter build apk --releaseThe app works without an API key using the public MBTA V3 endpoint (20 req/min limit). For higher rate limits, get a free key from api-v3.mbta.com and add it in lib/services/mbta_service.dart:
static const String _apiKey = 'your-key-here';This app was originally built in Swift/SwiftUI for iOS, then migrated to Flutter. The migration involved porting all 20 source files:
| iOS (Swift) | Flutter (Dart) | Notes |
|---|---|---|
| SwiftUI Views | Flutter Widgets | Declarative UI paradigm |
@StateObject / @Published |
Provider + ChangeNotifier | Reactive state management |
URLSession + async let |
Dio + Future.wait() |
Concurrent network calls |
UserDefaults |
SharedPreferences | Local persistence |
CoreLocation |
Geolocator | GPS + permissions |
DateComponents |
TimeOfDay + DateTime |
Date/time math |
This project is for educational and portfolio purposes.