Realtime Transit Board
Build a Flutter app that shows live arrival boards for public transport stops: which bus or tram comes next, in how many minutes, and whether it's late. Arrivals update continuously from a live feed, and the app deals with the realities of mobile networks: it reconnects on its own after losing signal, marks information as stale when it hasn't been updated for a while, and shows the last known board from its local Drift database when offline. Riverpod manages the app state, with the network, storage and screens kept cleanly apart. You'll learn streams in Dart, polling or WebSockets with automatic reconnection, Riverpod providers, local storage with Drift, and testing code that depends on time and the network.
- Estimate
- ~14.5h
- Steps
- 7
- Completed by
- 0
- Proposed by
- codeseed.app
Riverpod · Drift
Project roadmap
- 01
Define the feed and the app
~2hChoose a live data source: a real transit API with realtime arrivals (many cities publish one), or your own small mock server (for example in Dart with shelf) that sends arrivals for a few stops and can simulate delays and outages. Write README.md describing the data (stop, line, destination, expected and scheduled time) and the rules: when data counts as stale (for example after 60 seconds) and how reconnecting works. Done when: README.md describes the feed, and the data source works.
- 02
Build the live data client
~2.5hWrite an ArrivalsClient that exposes a Dart Stream of arrival lists for a stop, by polling every 15 seconds or listening on a WebSocket. Parse the data into typed classes, ignore duplicate or out-of-date updates, and report errors on the stream without closing it. Done when: listening to the stream prints updated arrivals for a stop.
- 03
Reconnect automatically
~2hWhen a request fails or the connection drops, retry after 1, 2, 4 and up to 30 seconds, resetting after success. Pause updates when the app goes to the background and resume when it comes back, using the app lifecycle. Expose the connection state (live, reconnecting, offline). Done when: stopping and restarting the data source makes the app reconnect by itself.
- 04
Cache boards with Drift
~2hCreate a Drift database with favorite stops and the last received arrivals per stop with the time they were received. Save each update, and show the cached board immediately when the app opens, before live data arrives. Done when: in airplane mode, the app shows the last known board for each favorite stop.
- 05
Build the boards with Riverpod
~2.5hCreate Riverpod providers for the client, the database and a board per stop that combines live and cached data. Build a favorites screen and a board screen listing arrivals with the line, destination, minutes until arrival (updated every few seconds) and delay in red. Show a banner with the connection state, and dim the board when data is stale. Done when: boards update live, and stale data is clearly marked.
- 06
Handle edge cases
~1.5hHandle arrivals that have already departed (remove them), a stop with no arrivals, times across midnight, and a feed returning broken data (keep the last good board and log the error). Let users add and remove favorite stops. Done when: none of these cases shows wrong times or crashes the app.
- 07
Test it
~2hWrite tests with a fake client and a controllable clock (for example package:fake_async): reconnect waits grow and reset, data becomes stale after the limit, departed arrivals are removed, and the cache is used when offline. Add a widget test for the stale banner. Done when: flutter test passes.
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack