

01
KIA airport buses
One database behind three apps, three websites and a Telegram bot, for Bengaluru's KIA-15, KIA-5 and KIA-5D airport routes.
I'm a mobile engineer in Bengaluru with four years of production work in React Native and Flutter. I usually own the whole line: the app, the API and admin portal behind it, the store release, and the fix when something breaks in the field.
| Project | Where | Status |
|---|
01.2 · About
ನಮಸ್ಕಾರ, I'm Girish. For the last four years I've built software that has to work on ordinary phones in ordinary conditions: a conductor checking the day's duty before the first airport run, someone comparing a branded strip with its Jan Aushadhi generic, a loan connector sending a lead from a shop counter.
At Techfino Capital, an RBI-registered NBFC, I build and support customer, partner and internal apps in React Native and Flutter, and the Node.js, FastAPI and PHP services they talk to. Broken builds, release days and production bugs that cross the app, the API and the database tend to end up with me.
Alongside that I build products for Bengaluru and Karnataka: three apps and a portal for the KIA airport buses, a generic-medicine finder and a government-jobs alert app. And Libella, a code editor, because I wanted to see how much IDE fits in a 5.5 MB download.
01.3 · Now
Updated 12 October 2026
TechFino Connector and TechFino AMS, two Flutter apps for Techfino Capital, are waiting on App Store review. The listings, screenshots and submission were scripted against the App Store Connect API.
Libella 0.2.1: parameter hints, quick fixes, workspace symbols and inlay hints, on top of the signed auto-update that arrived in 0.2.0.
A live map for KIA-15 that shows buses approaching you, drawn on BMTC's own route paths, with a 2, 5 or 10 km radius.
Three airport-bus apps and their portal: timetables, the daily crew rotation, and the route posters for the crew groups.
Zone 02
Products I've built and shipped, how the biggest one fits together, and the full list.
02.1 · Selected work


01
One database behind three apps, three websites and a Telegram bot, for Bengaluru's KIA-15, KIA-5 and KIA-5D airport routes.
02
A code editor with Git, a terminal, language servers and an AI agent, in a 5.5 MB download.

2,439 medicines21,286 KendrasWorks offline
03
Find the Jan Aushadhi generic for a branded medicine, what it saves you, and the nearest Kendra. Works offline.
04
Customer, partner and internal apps for an RBI-registered NBFC, from CredCo and the CRM to this year's Connector, AMS and HRMS.
02.2 · The KIA system
Every app, site and bot reads the same MySQL database through one small API. Point at a part, or tap it, to see what it does.
02.3 · Index
Zone 03
How I work, what I've learned the hard way, and the tools I reach for.
03.1 · How I work
An app is the smallest part of shipping one. I'd rather own the API, the admin screens, signing, the store listing and the support afterwards than throw them over a wall.
Every KIA app, site and bot reads one database. When a rule has to exist twice, in PHP on the server and Dart on the phone, a generated test keeps the two identical.
Simulators, real devices and live APIs, read-only by default. Libella's release binary runs a 32-step self-test of its own before I trust a build.
Over-the-air updates for JavaScript, a manual release button on the stores, a backup before every migration, and the migration before the code that needs it.
Every project carries a runbook: how to build it, how to deploy it, and what never to touch. The next person to read it is usually me, six months later.
03.2 · Field notes
Short write-ups of problems that took more than an afternoon. Open one for the cause and the fix.
DefaultReactHost builds its JSBundleLoader once per process, from a fixed path. The SDK's in-place reload re-ran that same loader. iOS re-reads bundleURL on every reload, which is why it never showed the bug.ReactHostImpl by hand, with a loader that asks for the bundle path every time JavaScript loads. Debug builds keep the default host. It compiles clean and goes out with the next Android release.object : JSBundleLoader() {
override fun loadScript(delegate: JSBundleLoaderDelegate): String {
val path = AppsAirPushModule.getJSBundleFile(applicationContext)
if (path.startsWith("assets://")) {
delegate.loadScriptFromAssets(applicationContext.assets, path, true)
} else {
delegate.loadScriptFromFile(path, path, false)
}
return path
}
}
Takeaway When a framework caches something, find out exactly when it reads it.
MapView on both. On Home, the map is only created once it scrolls into view.<MapView
// a new route or circle means a new map
key={`${route?.routeId ?? 'no-route'}|${center ? radius : 'no-circle'}`}
ref={map}
style={styles.fill}
>
Takeaway If a native view ignores updates, make the update a remount.
kia_15_routes and uploaded the schema file before the ALTER had run. For about a minute, every read of that table failed.*. One column in the file that wasn't in the table made every query invalid.-- 1. the database first
ALTER TABLE `kia_15_routes`
ADD COLUMN `driver_id` VARCHAR(20) NULL AFTER `profilepic`,
ADD COLUMN `driver_name` VARCHAR(150) NULL AFTER `driver_id`;
-- 2. then tableSchema.php, 3. then the portal
Takeaway Order a deploy so that every step in between still works.
flutter test replays every case against the Dart code. Udyoga Alerts does the same for listing status: one date rule, two languages, 726 cases.php backend/tests/make_search_vectors.php # PHP writes the expected results
flutter test # Dart has to match every case
Takeaway If logic must live in two places, let a test be the source of truth.
<style> tags. In the Android build the text area was blank and only the line numbers showed.style-src in the app's Content Security Policy. Once a nonce is present, browsers ignore 'unsafe-inline', so every style CodeMirror injected was blocked.style-src (scripts keep their nonces), and add a self-test step that checks the editor really renders text."security": {
"dangerousDisableAssetCspModification": ["style-src"]
}
Takeaway Test what the user sees, not just what loaded.
postinstall script in all sixteen React Native and Expo apps patches the CLI so it finds the new simulator. Every Podfile lifts pods to iOS 15.1. A SceneDelegate starts React Native in a window scene, done first for the three transit apps.installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
current = config.build_settings['IPHONEOS_DEPLOYMENT_TARGET']
if current && current.to_f < minimum_ios.to_f
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = minimum_ios
end
end
end
Takeaway Fix it once, in a file every project shares.
03.3 · Toolbox
Zone 04
Where I've worked, written like a changelog.
04.1 · Experience
Jun 2022 → now
Alongside
Jan 2021 → May 2022
Education
Zone 05
The end of the line.
Bengaluru, IST (UTC+5:30). It's here now.
Case study 01 · Transit
BMTC's Vayu Vajra buses run between the city and Kempegowda International Airport. KIA-15, KIA-5 and KIA-5D are three of those routes. I built the apps their crews and passengers use, and everything behind them.
The routes began as separate apps on separate backends, first Firebase and then Supabase. Every new screen meant deciding which copy of the data was right. In September 2026 I moved all of them onto one MySQL database behind a small PostgREST-style API, so every app, site and bot now reads the same rows.
Case study 02 · Desktop
A code editor for macOS, Windows, Linux and the browser. It started with one rule: every download under 50 MB. That ruled out a fork of VS Code on Electron, so Libella runs on Tauri 2, a Rust core with the system's own web view. The name is Latin for a spirit level.
ignore crate.Case study 03 · Health
Jan Aushadhi Kendras sell generic medicines for a fraction of branded prices, but working out the generic for what is on your prescription is hard. Aushadha Mitra makes it a search. It is an independent app, not an official PMBI or government one, and it says so.
Case study 04 · Fintech
Techfino Capital is an RBI-registered NBFC in Bengaluru that offers MSME and education loans. I've been a Senior Software Developer there since June 2022, across mobile, backend and releases.
Professional work. These apps aren't linked here.