Skip to content
The house
In developmentPublic transit · Montevideo · open source

Three websites to catch one bus. Now it is one app.

MVD Transporte puts the city’s own transit services — the STM card account, top-up, Cómo Ir and live arrivals — behind one bottom bar, and adds what they lack: saved stops, an alert before the bus arrives, a home-screen widget. Unofficial, free and open source.

The problem

The services exist. They do not talk to each other.

Montevideo publishes most of its public transport online: the STM card account and its top-up, the Cómo Ir journey planner, next-arrival times for every stop. Each one lives at its own address, in its own layout, behind its own login. Checking whether there is money on the card and when the next bus reaches the corner means three sites and a lot of waiting for pages that were not built for a phone.

None of it needs rebuilding. The data and the accounts belong to the city and should stay there. What is missing is the layer on top: one place to open, the stops you actually use, and a notification that arrives before the bus does rather than after it.

What it does

One bar for the whole system

The STM account, quick top-up, notices and Cómo Ir open as tabs inside the app. The pages are the city’s own, so nothing about the account is copied or re-implemented.

My stops, with live arrivals

Save the stops you use by number and see the next buses at each one, read from the city’s public arrivals feed. A route planned in Cómo Ir can be saved in one tap.

Alerts before the bus

A background check every fifteen minutes warns when a bus on a saved stop or route is within the minutes you chose. No account to create and nothing to keep open.

Widget and lock

On Android, a home-screen widget shows the card balance and the next bus on your route. A biometric lock keeps the STM account closed when the phone is lent out.

Under the hood

A wrapper where it should be, native where it helps.

Flutter, one codebase for Android and iOS. The city’s pages run in a WebView as published; saved stops, routes and alerts are native, stored on the device with Hive and checked in the background by WorkManager. There is no server of ours in the path and no sign-up: nothing leaves the phone except requests to the city’s own services.

// WorkManager, every 15 minutes, on the phonefor (final stop in CacheService.getStopsWithNotificationsEnabled()) {  final buses = await MvdApiService.getNextArrivals(stop.id);  buses.where((b) => b.etaMinutes <= stop.etaAlertMinutes).forEach(alert);}

Built with

  • Flutter · Dart
  • WebView
  • Hive
  • WorkManager
  • Local notifications
  • Home-screen widget
  • Montevideo transit API

Three websites to catch one bus. Now it is one app.