Mobile app stack
React Native and Flutter app development — native when it matters
We pick the mobile framework that fits your product, not the one we happen to like. Every option has a fixed, proven core stack and the same security baseline.
Choosing a framework
Which framework we use when
React Native and Flutter app development covers most products with one shared codebase for iOS and Android. Native Kotlin and Swift are reserved for single-platform apps that need deep integration with the device. Each app uses exactly one framework — we never mix two inside the same app.
| Situation | Framework | Why |
|---|---|---|
| Cross-platform, fast delivery, team knows React/TypeScript | React Native (Expo, TypeScript) | One TypeScript codebase for iOS and Android that shares types and skills with our web stack. |
| Cross-platform with strong custom UI and animation | Flutter (Dart, Riverpod) | Its own rendering engine draws pixel-perfect custom interfaces consistently on both platforms. |
| Android-only with deep platform integration | Native Android (Kotlin, Jetpack Compose) | Full access to Android features such as home-screen widgets, Wear OS and NFC. |
| iOS-only with deep platform integration | Native iOS (Swift, SwiftUI) | First-class access to Apple frameworks such as widgets and Live Activities. |
| Existing native app gaining a new feature | Stay native (Kotlin or Swift) | Adding a second framework to a working app raises cost and risk, so the new feature is built natively. |
Cross-platform, fast delivery, team knows React/TypeScript
- Framework
- React Native (Expo, TypeScript)
- Why
- One TypeScript codebase for iOS and Android that shares types and skills with our web stack.
Cross-platform with strong custom UI and animation
- Framework
- Flutter (Dart, Riverpod)
- Why
- Its own rendering engine draws pixel-perfect custom interfaces consistently on both platforms.
Android-only with deep platform integration
- Framework
- Native Android (Kotlin, Jetpack Compose)
- Why
- Full access to Android features such as home-screen widgets, Wear OS and NFC.
iOS-only with deep platform integration
- Framework
- Native iOS (Swift, SwiftUI)
- Why
- First-class access to Apple frameworks such as widgets and Live Activities.
Existing native app gaining a new feature
- Framework
- Stay native (Kotlin or Swift)
- Why
- Adding a second framework to a working app raises cost and risk, so the new feature is built natively.
Core stack
The libraries behind each framework
Every developer working in a framework uses the same core libraries, so any of them can maintain or extend the app.
TypeScript
React Native
Chosen for cross-platform apps when speed of delivery matters and the team or product already works with React and TypeScript.
- UI
- Expo development builds (not Expo Go), React Navigation and NativeWind styling
- State management
- TanStack Query for server data; component state first, Zustand for small shared app state
- Networking
- Typed client generated from our OpenAPI specification, wrapped in TanStack Query hooks; forms with React Hook Form and Zod
- Local data
- AsyncStorage or MMKV for cached data and settings only — never for tokens
- Secure storage
- expo-secure-store or react-native-keychain, backed by Keychain on iOS and Keystore on Android
- Testing
- Jest and React Native Testing Library; Maestro or Detox for end-to-end flows
- CI/CD
- EAS Build and EAS Submit; EAS Update over the air for JavaScript-only fixes, with any native change going through store review
Dart
Flutter
Chosen when the experience depends on highly custom, animated UI that must look identical on iOS and Android.
- UI
- Flutter with Material 3, one shared theme with light and dark mode, and go_router navigation
- State management
- Riverpod (flutter_riverpod with riverpod_generator)
- Networking
- Dio with a typed client and models built from our OpenAPI specification
- Local data
- Drift (SQLite) for offline data; shared_preferences for non-sensitive settings only
- Secure storage
- flutter_secure_storage (Keychain / Keystore)
- Testing
- flutter_test and mocktail for unit and widget tests; integration_test for end-to-end flows; golden tests for key visuals
- CI/CD
- Fastlane or Codemagic pipelines
Kotlin
Native Android
For Android-only products that need deep platform integration, such as widgets, Wear OS or NFC.
- UI
- Jetpack Compose with Material 3, type-safe Compose Navigation and Coil for images
- State management
- MVVM with ViewModel, Kotlin Coroutines and Flow; Hilt for dependency injection
- Networking
- Retrofit with OkHttp and kotlinx.serialization
- Local data
- Room for offline data; Jetpack DataStore for non-sensitive preferences
- Secure storage
- Android Keystore with EncryptedSharedPreferences
- Testing
- JUnit5, MockK and Turbine for unit tests; Compose UI tests and Espresso
- CI/CD
- Gradle (Kotlin DSL, version catalogs) with Gradle Play Publisher or Fastlane
Swift
Native iOS
For iOS-only products that need the latest Apple frameworks, such as widgets, Live Activities or deep device integration.
- UI
- SwiftUI with NavigationStack; UIKit only to fill a specific gap
- State management
- MVVM with @Observable view models and Swift Concurrency (async/await, actors)
- Networking
- URLSession with async/await and Codable
- Local data
- SwiftData (Core Data on older projects); UserDefaults for non-sensitive settings only
- Secure storage
- Keychain Services
- Testing
- Swift Testing and XCTest for unit tests; XCUITest for UI flows
- CI/CD
- Fastlane with Xcode Cloud or GitHub Actions, delivering through TestFlight
Mobile security baseline
Six protections every app ships with
Mobile apps run on devices you don't control, so security is designed in from the first sprint, not bolted on before launch.
Secure token storage
Tokens live only in Keychain on iOS and Keystore-backed storage on Android — never in plain preferences or files.
Short-lived JWT + rotating refresh
Access tokens expire quickly and refresh silently in the background. If a refresh fails, the user is signed out.
Extra protection for sensitive apps
Finance, health and credential apps add certificate pinning with a planned rotation, and hide sensitive screens in the app switcher.
No secrets inside the app
Third-party API keys stay on our servers and are called through the backend, so they cannot be extracted from the app.
Deep links are verified
A link that opens the app never triggers a privileged action on its own — the server checks the user is allowed first.
Obfuscated release builds
Release builds are minified and obfuscated, making reverse engineering of business logic significantly harder.
Quality standards
What every app has to meet before launch
Security is only part of a good app. These standards apply to every framework, so the app works for all of your users, on good and bad connections.
Accessible by default
Screen readers can complete every key journey, text follows the phone's size setting and tap targets are large enough to hit.
Clear offline behaviour
Each feature is designed as online-only, cached or fully offline. Changes made offline are queued and synced safely later.
Performance budgets
The first screen should be usable in about two seconds on a mid-range phone, with long lists and images loaded efficiently.
No blank or broken screens
Every screen that loads data shows a clear loading, empty and error state, with a way to retry.
Tested on real journeys
Automated end-to-end tests cover sign-up, login and core actions, and we test on the oldest supported OS version before release.
Crash monitoring
Crash reporting is live from the first build, and a drop in the crash-free session rate blocks the release.
Release practices
How updates reach your users safely
Store releases cannot be undone instantly, so every release follows the same controlled process.
Separate test and live builds
Development, staging and production builds connect to their own servers and look different, so testers never touch live data.
Automated checks before signing
A release is signed only after automated linting, tests and a clean build pass in CI.
Staged rollouts
New versions reach a small share of users first through Play staged rollouts and App Store phased releases.
A rollback plan, every time
Before a rollout starts we know how to pause it or ship a fix, so a problem reaches as few users as possible.
One backend
Every app consumes the same versioned REST API
Our mobile apps use the same /v1 REST API as the web app, described by one OpenAPI specification with one error format. Business rules and permissions are enforced on the server, never only in the app, and each app’s data models are generated or mirrored from that same specification. One set of rules means lower cost, no drift between platforms and safer releases.
FAQ
Mobile app stack: frequently asked questions
Not sure which framework fits?
Share your app idea and target users. In a free 30-minute consultation we will recommend a framework and explain the trade-offs in plain language.
Keep exploring
Related pages
- ServicesMobile App DevelopmentiOS and Android apps with React Native, Flutter or native.Learn more
- TechnologyWeb & Backend StackNext.js, NestJS, TypeScript, PostgreSQL and Prisma.Learn more
- TechnologyWhy Our Tech StackLearn more
- TechnologyAI StackModels, frameworks, vector databases and deployment.Learn more