Singapore Buses v2026 is out now. It's been a challenging development cycle, to say the least, and I'm glad it's over. The Design Diaries series covers the major Liquid Glass updates. This post looks at some of the other technical changes that have been made in the v2026 update.

GRDB

Singapore Buses, has always, always, always—way back to 2018 when it was SG Transit—used Core Data. Even when SwiftUI came along, followed by SwiftData, it stuck with Core Data. Not any more. It's now using GRDB.

Each app version is seeded with an updated SQLite database containing the latest bus stops, routes, and services. This database is created using a separate app on the Mac. Long-term, the aim is to move away from having to release new app versions with an up-to-date database and instead move to an over-the-air model that refreshes the database in the background. The move to GRDB should smooth the path.

Map Performance

The database is now loaded into memory instead of being read from disk. As a result, panning the map and determining what bus stops to show (or hide) is now instantaneous instead of requiring a small pause and the end of the pan gesture. It's a simple call site:

.onMapCameraChange(frequency: .continuous) { context in
    model.showStops = context.camera.distance < 9500 // hide stops when above 9,500m
    Task {
        await model.updateVisibleBusStops(context.rect)
    }
}

App Clip

Singapore Buses now contains an App Clip with arrival estimate UI.

When users share estimated arrival times from the main app, text is generated with the current arrival times along with a URL: https://clips.singaporebuses.app?... That URL has the following query parameters:

Parameter Usage Example
c Bus Stop Code 08138
n Bus Stop Name Concorde Hotel S'pore
r Road Name Orchard Rd
s Service No 174
lat Latitude 1.3004785730821
lon Longitude 103.841847006076
e Expiry 1757767987
v HMAC Validation signature

The parameters c, n, and r are used to populate the UI in the App Clip, while lat and lon are used to determine if a Look Around view can be displayed. s in conjunction with c are used to query the LTA API for the latest estimates. e is the time the App Clip expires, and v is a signature that is validated to make sure the URL is genuine.

If the recipient has Singapore Buses installed, tapping the link opens the app and presents arrivals for that bus stop. Otherwise, an App Clip launches with the same bus arrival UI as the main app and updates arrival estimates every 15 seconds for 10 minutes...then invites the user to download the app from the App Store.

The clips.singaporebuses.app subdomain is powered by Cloudflare Workers. It serves an AASA, some basic content, and a favicon, but is otherwise is there to enable redirects to the app or the App Clip.

This is the first time I've implemented an App Clip. I'm interested to see how (or if) it affects download statistics.

iPad Support

Given that iPadOS is, in my opinion, the star of the 26 series of OS updates, it only made sense to extend Singapore Buses to the iPad. It now has a native layout with some iPad specific niceties, like keyboard shortcuts and a full-screen route views.

(I've never seen anyone actually use an iPad at a bus stop in Singapore. With that in mind, Singapore Buses will be on Apple Watch in the future.)

LandTransportKit

Lastly, all interaction with the Land Transport API is now handled with LandTransportKit.

I've open sourced this package—it's free for anyone to use!