Jalan
Record every bus and MRT ride, see each journey on the map, and find your fastest and cheapest commute.
- status
- beta
- url
- jalan.how ↗
- started
- 09/2026
- stack
- Go · SQLite/Turso · Hotwire · LTA DataMall + OneMap

## why
As someone who takes public transport in Singapore every day, I find the buses and MRT here very satisfactory, except for a few very niche parts.
- I cannot see how much a trip actually costs in real time. When using credit cards, the total fare for the whole day is aggregated and only shows up the next day. With EZ-Link cards, you can see a preview of the fare when tapping in on the bus or at the MRT gantry, but it’s only for a brief moment. Checking the details in the SimplyGo app doesn’t help either, since it usually only shows the aggregated data a couple of days later.
- When commuting between home & work, there are several public transport options available, which vary from bus-to-bus transfers to a couple of bus-to-train transfers via different train stations. And I can never really compare them in terms of speed & cost.
This is why I started working on Jalan (which literally means “go” in Malay/Indonesian). It’s not really a public transport planner, but more of a logger/tracker. Use it for several days during your day-to-day commute, and it can give you a summary of how much you actually spent and which routes are the best for your routine trips.
Fun fact: the domain is jalan.how, a play on the Singlish “Jalan how?”, which is exactly what the app is trying to answer.
## how it works
01 pick your ride Tap Bus to see the nearest stops with their next arrivals and how full each bus is, or MRT for the lines at the nearest stations. The first ride starts a journey, later ones are transfers. Each tap saves the time and a location fix.
02 see it on the map Every ride is matched to the stop or station it started at, and the route is drawn from LTA DataMall data on top of OneMap, Singapore's official map.
03 know the fare When a journey ends it's priced at the adult card fare, with rides grouped into fare journeys by the transfer rules. If a stop or time was wrong, adjust the journey or add a ride you forgot, and the fare is worked out again.
04 learn your commute Tag journeys like Home to Work and each commute gets its own page with the typical time, fare and departure, the routes you take and how the trip time trends. After three trips, a journey in progress shows roughly how long is left.
## stack
- Go net/http + html/template// backend
- The Go server renders every page as plain HTML with Go's standard library.
- SQLite / Turso// database
- SQLite for fast iteration in development; Turso, a hosted SQLite, in production.
- LTA DataMall// data
- Bus stops, bus routes, MRT/LRT stations and fares come from Singapore's Land Transport Authority DataMall. The bus arrivals is fetched live from LTA API.
- Turbo + Stimulus// frontend
- They avoid full page reloads, and they keep the app one long-lived page, so the phone asks for location once per launch instead of on every screen.
- Leaflet + OneMap// maps
- OneMap is Singapore's official map, used both as the basemap and to draw bus rides along their real route. Leaflet only loads on pages that show a map.
- Fly.io// infra
- Cheap, and friendly to both users and agents.
$ git log --oneline --all
- docs/new-regionsplanned
- HEAD → main2026-10-05
Pages swap in place with Turbo; the app's JavaScript is split into Stimulus controllers
Now that the app has settled into its final shape, this version makes it snappier: interactions no longer re-render the whole page.
- 2026-10-03
Adjust a finished journey's stops and times
For when you forget to tap during a journey: fix the boarding times, or add a missing transfer between rides.
- 2026-09-30
Commutes: tag journeys and see what each trip is usually like
Journeys can be tagged with a commute (e.g. Home → Work); the app then compares the routes and shows which is fastest and cheapest.
- 2026-09-29
Bus picker with live arrivals
New quality-of-life feature for the bus picker: shows each bus's estimated arrival time and how crowded it is, using LTA's Bus Arrival API.
- 2026-09-29
Fares estimated automatically when a journey ends
Each tap is saved with a GPS fix, which is matched against LTA DataMall's open data to work out the route, the distance travelled and the estimated fare.
- 2026-09-28 · initial commit
Record bus and MRT journeys
The first MVP: the browser's location API records where you are at each tap, and OneMap draws the finished journeys.