grig-teo:~$
light
← back to articles

Building Cross-Platform Mobile Apps Without Regret

When one React Native codebase is right, when it is a fight with the platform, and the release work nobody budgets for.

There is no default answer

"Cross-platform or native" is usually argued as a matter of taste. It is not. It is a question about the feature list, and getting it wrong costs months.

I have shipped both ways. Android in Kotlin with OpenCV document detection and a shared Kotlin Multiplatform module at Crossinx. Three GlavUpDK apps where the Avto suite is React Native with Expo on top of a FastAPI backend, while the OTRS client is deliberately native. And an iOS app of my own that talks to a smart ring over Bluetooth Low Energy.

Choose cross-platform when the app is mostly forms and lists

If the screens are lists, forms, a detail view and an API call, one React Native codebase is the honest choice. You pay once for the navigation, the auth flow and the build pipeline, and you get both stores.

The Avto suite fits that description: service orders, vehicle records, a login, a backend that already exists. Expo handled the build, the updates and the store lanes, and none of it needed the platform.

Choose native when the feature is the platform

The deciding signal is whether your core feature is a platform capability or a screen. Bluetooth, camera pipelines, background execution, sensor fusion, encrypted local storage. If one of those is the product, the cross-platform layer becomes a translation layer between you and the hardware, and you spend the project fighting it.

The ring app is the obvious case: reading a device-specific binary protocol over BLE, handling reconnects, sleeping between polls. Nothing about that belongs behind a JavaScript bridge.

Offline matters too. The Gosti app runs at diplomatic protocol events where the network may not exist. Local encrypted storage, a biometric gate before export and screenshot blocking are not features I could source from a cross-platform plugin and trust.

What sharing really looks like

Kotlin Multiplatform was the best middle ground I have used: the domain model, the validation and the business rules live once, compiled natively for Android and iOS, while each platform keeps its own interface. You share logic, not screens. That keeps the parts worth sharing shared without dragging the interface into a compromise.

Budget for the release pipeline, not just the code

The build and the store are where mobile projects actually slip. Signing keys, version codes, device test farms, screenshots, review rejections for missing privacy declarations. I automate it: Fastlane lanes on iOS, EAS on Android, CI running the device tests with a coverage gate so a red build cannot become a release.

That work is invisible in a demo and is the difference between shipping monthly and shipping once.

The decision rule I use

Write the feature list, mark every item that needs the platform, and count. Zero or one of those, and cross-platform wins on cost. Three or more, and native wins on time even though it looks more expensive on day one.

The mistake is choosing the codebase on taste and then discovering the platform question in month four, when the architecture is already shaped around the wrong answer.

Building Cross-Platform Mobile Apps Without Regret | grig-teo