Support

Lesson 5 of 11 ·9 min read

Cross-Platform Frameworks Compared

Flutter vs React Native vs Kotlin Multiplatform: three different bets about what to share.

After this lesson you can explain

  • Which layer each framework shares (pixels, widgets, or logic only), and why every strength and weakness flows from that one choice.
  • Why the team you already have, not a benchmark, usually decides between Flutter, React Native, and Kotlin Multiplatform.
  • What stays identical regardless of framework: the API client, token auth, push, and the release pipeline.

1. The problem, and the one question that organises everything

Building the same app twice (Kotlin for Android, Swift for iOS) doubles cost and guarantees the two versions drift out of sync. Every cross-platform framework is an answer to one question:

Which layer do we share, and which do we keep native? Flutter shares everything down to the pixels. React Native shares the logic and borrows the platform's widgets. Kotlin Multiplatform shares the business logic and keeps the UI fully native. Every strength and weakness of each framework flows from its answer.

                    UI pixels    UI widgets    Business logic    Language
Fully native x2       native       native         written twice    Kotlin + Swift
Kotlin Multiplatform  native       native         SHARED           Kotlin (+ Swift UI code)
React Native          native       SHARED*        SHARED           JS/TS      (*real native widgets,
Flutter               SHARED       SHARED         SHARED           Dart        driven from shared JS)
Web wrapper           SHARED       SHARED (web)   SHARED           JS/TS + HTML/CSS

2. The three contenders

Flutter (Google)

Share everything, including the pixels

Written in Dart. Flutter does not use the platform's UI widgets at all: it ships its own rendering engine and draws every pixel itself, the way a game engine would. A Flutter button is a Flutter-drawn picture of a button.

  • Upside: total consistency. The app looks identical on Android, iOS, web, and desktop, and never waits for a platform widget to catch up. Excellent tooling (hot reload, strong typing) and first-class Google backing.
  • Downside: the same coin's flip side. The app is only ever as native-feeling as Flutter's imitation; when Apple ships a new design language, Flutter must re-implement it. Dart is a you-only-use-it-here language. Platform APIs (Bluetooth, Keychain, health data) go through platform channels or community plugins.
  • Used by: Google Pay, BMW, Alibaba, eBay Motors; the most popular choice for greenfield startup apps.
  • Sweet spot: fresh starts with no web or native legacy, and brand-heavy custom UIs that would have been hand-drawn anyway.

React Native (Meta)

Share the logic, borrow the platform's widgets

Written in JavaScript/TypeScript with React. Components render as real native widgets: an RN button on iOS is an actual UIKit button, driven from JS. The old asynchronous "bridge" that earned RN its slow reputation is gone, replaced by JSI and the Fabric renderer (JS calling native code synchronously), so the classic performance complaints are largely dated.

  • Upside: ecosystem gravity. A React web team is productive in week one, knowledge (and some code) is shared with the website, and npm is the largest package ecosystem in existence. Expo, the de facto standard toolchain, packages builds, native modules, and over-the-air JS updates (ship fixes without a store review, within store policy limits).
  • Downside: the JS world's churn comes along: dependency upgrades and breaking changes are a recurring tax. Truly custom rendering (canvas-heavy UIs) fights the model.
  • Used by: large parts of Meta's own apps, Shopify (all-in), Microsoft (Office and Outlook surfaces), Discord.
  • Sweet spot: web-first teams, and products where the website and app should feel like siblings.

Kotlin Multiplatform / KMP (JetBrains)

Share the business logic, keep the UI fully native

Inverts the bet. Networking, storage, sync, and domain logic are written once in Kotlin and compiled natively for each platform; the UI stays SwiftUI on iOS and Jetpack Compose on Android. No imitation layer anywhere.

  • Upside: genuinely native apps on both platforms, with the duplicated-logic problem solved. Adoptable module by module: you can migrate one sync engine into shared Kotlin inside an existing native app, which neither Flutter nor RN can do gracefully. Officially supported by Google for Android teams.
  • Downside: you still write two UIs, so it saves less than the other two. iOS developers must consume Kotlin-compiled frameworks, which adds friction. The optional Compose Multiplatform extension shares the UI too (Flutter-style); its iOS support is now stable but the ecosystem is still young.
  • Used by: Netflix, McDonald's, Forbes, Cash App.
  • Sweet spot: teams that already have two native apps and want to converge them gradually without giving up native UI.

3. Side by side

FlutterReact NativeKotlin Multiplatform
LanguageDartJavaScript / TypeScriptKotlin (+ Swift for iOS UI)
UI renderingOwn engine draws every pixelReal native widgets, driven from JSFully native UI per platform
Code shared~95–100%~85–95%~40–70% (logic only; more with Compose MP)
Native look and feelImitated (very good, not perfect)Genuine widgets, JS-driven behaviourGenuine, indistinguishable from native
PerformanceExcellent; compiled, own rendererGood; JSI closed the old gapNative, by definition
Beyond mobileWeb + Windows/macOS/Linux from same codeWeb via react-native-web; desktop nicheServer, desktop, web (logic); UI via Compose MP
Hiring poolGrowing; Dart learned on the jobEnormous (every React developer)Android/Kotlin developers
Incremental adoption in an existing native appPoorPossible but awkwardDesigned for it
Backed byGoogleMeta (+ Microsoft, Expo)JetBrains (+ Google endorsement)
Main riskNon-native feel where it matters; Dart lock-inJS dependency churn; upgrade taxLeast code shared; iOS-side friction

4. The decision logic

Your situationPickBecause
Team already knows React / you have a React website React Native (with Expo) Week-one productivity and shared knowledge beat any technical nicety of the alternatives
Existing native apps and native team Kotlin Multiplatform Only option adoptable module by module; stops the duplicate-logic bleeding without a rewrite
Fresh start, no web legacy, design-led UI Flutter Fastest single-codebase route to a polished custom UI on both platforms
Product is really a website (content, forms, dashboard) None: Capacitor or a TWA Wrap the web app; a full framework rewrite buys little (see Web Apps vs Native Apps)
Value lives in cutting-edge platform features (ARKit, widgets, watch, health) Fully native, twice Cross-platform teams wait for wrappers; native gets platform features on day one

The meta-point: all three are platform followers. When Apple or Google ships a new OS capability, native developers use it that day; cross-platform teams wait for the framework or write the glue themselves. The more of your app's value that lives in platform-specific features, the weaker the case for any cross-platform framework. The more your app is "UI over an API" (most apps), the stronger it gets.

5. What stays the same regardless of choice

Worth noticing across the whole course: the framework choice changes the UI layer and the language, and almost nothing else.

  • The app is still an API client: same HTTPS, JSON, status codes, pagination.
  • Auth is still token-based: secure storage, bearer headers, refresh rotation (the login-flow lesson applies verbatim in all three).
  • Push still runs through FCM/APNs with the same registration and token-hygiene loop.
  • Shipping is still the signed-bundle → review → staged rollout pipeline, with the same backwards-compatibility pressure on your API.

Which is the real conclusion: the backend and the API contract are the durable investment. Frameworks come and go on roughly five-to-ten-year cycles; a well-designed API outlives all of them.

Check your understanding

  • Which layer does each of the three frameworks share, and which does it keep native?
  • Why is Kotlin Multiplatform the only one of the three that can be adopted module by module inside an existing native app?
  • Name two parts of the app stack that stay identical no matter which framework you pick.

Reviewed 4 August 2026.