From Native to Multiplatform Development: Unpacking Kotlin and Compose

Authors
Dominik Dolny
Software Engineer
@
Callstack

As a React Native developer, you're probably familiar with writing once and running everywhere. React Native lets you share both UI and business logic, creating apps for iOS and Android using a single JavaScript codebase.

But recently, you may have heard about Kotlin Multiplatform (KMP), Jetpack Compose, and Compose Multiplatform—and it’s not immediately obvious how they fit together. Are they like React Native? Do they replace native development entirely? How do these tools relate to each other?

Let’s explore these technologies from the perspective of a React Native developer, break down the confusion, and see how they compare to what we know.

What is Kotlin Multiplatform (KMP)?

Kotlin Multiplatform is a feature of Kotlin that enables developers to share business logic, data layers, and other non-UI code across multiple platforms, such as Android, iOS, Web, and Desktop. Unlike React Native, Kotlin Multiplatform doesn’t aim to replace native UI development entirely. It can be implemented in an existing application.

How Does It Work?

KMP lets you write platform-agnostic code in Kotlin and provides tools to integrate platform-specific code (e.g., Swift for iOS, Java/Kotlin for Android) where necessary.

Unique Approach - Unlike other cross-platform solutions that attempt to share everything, including UI, KMP focuses on sharing the core logic while allowing native UI on each platform.

What are typical use cases?

At any point in Android app development process, logic and classes can be separated into multiplatform module and used on other platforms. A common module can contain logic responsible for the REST communication, data storage, caching, data mapping/modification, and many more. KMP supports also JUnit and TestNG, so the code can be tested.

You’ve got a few different options to implement KMP.

how you can implement KMP

Sharing Individual Modules

You can share simple Kotlin Multiplatform (KMP) modules, such as those for analytics or networking, by writing them once in Kotlin and reusing them across all platforms.

This approach is ideal for large existing projects that are difficult to refactor. It allows for a gradual adoption of KMP, introducing it one module at a time and focusing only on areas that align with the project’s requirements.

Sharing the Data Layer

You can use Kotlin to write the entire data repository, integrating various data sources (e.g., web services, local settings, databases, GraphQL) with KMP libraries like Ktor HTTP Client, MultiPlatformSettings, SqlDelight, or Apollo GraphQL.

This approach suits existing projects where the data layer can be fully rewritten without excessive complexity or for new projects that prefer a cautious adoption of KMP. However, it requires maintaining platform-specific ViewModel and UI layers, which can become a significant maintenance challenge.

Sharing Both Data Layer and ViewModel

In addition to sharing the data layer, you can also share the ViewModel in KMP, defining all the data required by the UI layer.

This is the most compelling approach, as the platform-specific code is limited to the UI layer. It works especially well for new projects that use declarative UIs, such as Jetpack Compose (Android) and SwiftUI (iOS). With thin, stateless UI layers, this method enables sharing over 80% of the codebase using KMP.

What is Jetpack Compose?

Jetpack Compose is a modern, declarative UI framework developed by Google for building native Android UIs. It simplifies UI development by using a reactive, Kotlin-first approach. Think of Jetpack Compose as Android’s answer to React Native’s declarative UI approach—but built exclusively for native Android.

Compose focuses exclusively on creating UIs for native Android apps. It's a replacement for the traditional XML-based UI toolkit.

What is Compose Multiplatform?

Compose Multiplatform is an extension of Jetpack Compose developed by JetBrains to create declarative UIs across multiple platforms, such as Android, Desktop, and Web.

Relation to KMP

Compose Multiplatform can be used as the UI layer in a Kotlin Multiplatform project, but it is not part of Kotlin Multiplatform itself. Instead, it’s a toolkit that complements KMP by enabling shared UIs.

How are Jetpack Compose and Compose Multiplatform Different?

  1. Scope:
    • Jetpack Compose: Focused solely on Android.
    • Compose Multiplatform: Designed for multiple platforms, including Android, Desktop, and Web.
  2. Developers:
    • Jetpack Compose: Maintained by Google as part of the Android ecosystem.
    • Compose Multiplatform: Maintained by JetBrains to align with Kotlin’s multiplatform capabilities.
  3. Use Cases:
    • Jetpack Compose: For building Android-specific UIs.
    • Compose Multiplatform: For sharing UIs across platforms in Kotlin Multiplatform projects.
Many developers assume Jetpack Compose and Compose Multiplatform are the same because they share APIs and design patterns. While they are related, their scope and purposes differ significantly.

Also, it’s important to note that Kotlin Multiplatform itself is not tied to any specific UI framework. You can use native UIs or Compose Multiplatform depending on your project needs.

Conclusions

Kotlin Multiplatform, Jetpack Compose, and Compose Multiplatform are part of the evolving Kotlin ecosystem, but they solve different problems. Understanding these distinctions helps developers pick the right tools for their needs, whether building native Android apps, shared business logic, or fully shared multiplatform UIs.

For a React Native developer, Kotlin Multiplatform may feel like a paradigm shift because it doesn’t mandate sharing everything. Instead, it gives you the freedom to choose—share logic where it makes sense and build UIs natively or with tools like Compose Multiplatform

By embracing this flexibility, KMP allows you to balance shared code with the platform-specific experience users expect. If you’re exploring alternatives to React Native, Kotlin Multiplatform is worth a look at—not as a replacement but as a complementary option that excels in performance, flexibility, and native integration.

Insights

Learn more about Cross-Platform

cover

Feb 27Article

Sparkling: The Missing App Layer for Lynx.js?

A hands-on look at Sparkling for Lynx.js: CLI, native navigation, and the tooling layer that turns Lynx into a full mobile app framework.

cover

Feb 12Live Stream

Sparkling: A New Framework for Lynx

Join the Lynx team live as we explore Sparkling, its boundaries with Lynx, core features, and bootstrap a project from scratch.

cover

Dec 19Article

Visualizing the Dual-Thread Model of Lynx JS

A practical look at Lynx JS’s dual-thread runtime, using real examples to show how main and background threads behave under load.

cover

Dec 2Live Stream

Two Threads of Lynx.js Part 2

Learn how Lynx.js uses a dual-threaded model, how its APIs work, and what it means for performance in this live session with Lukasz Chludzinski and Kewin Wereszczynski.

cover

Nov 27Live Stream

Exploring Lynx.js and Its Two-Thread Runtime

A recap of our live session exploring how Lynx.js splits work across a main thread and a background thread.

cover

Nov 7Article

Exploring Lynx JS: From Quick Start to CLI Workflows

Learn how to set up Lynx JS, explore its ecosystem, and use the Community CLI to build native apps with a familiar JavaScript workflow.

cover

Sep 19Podcast

React Native at Scale With NFL

Discover how the NFL uses React Native, Expo, and a monorepo to ship apps across iOS, Android, web, and TV with one stack.

cover

Aug 5Article

How Node-API Works in React Native: A Deep Dive

A closer look at how Node-API works in React Native, covering addon loading, bundling, the host package, and new build tools like cmake-rn and ferric-cli.

cover

Feb 7Article

Bringing WebAssembly to React Native With Polygen

Discover Polygen, a toolkit that brings WebAssembly to React Native, compiling WASM to C for near-native performance with no runtime overhead.

cover

Dec 3Article

Aiming for Success in the TV App Development Space With React Native

Learn how to handle platform differences, optimize user interactions, and balance standardization with customization when building a React Native app for TV.

cover

Aug 7Podcast

Open Mobile Hub: Non-GMS and Cross-Platform Possibilities

When you build applications, do you ever consider users who may not have access to Google Mobile Services? They may not be your target audience now, but it's good to be aware of what options you have in store for non-GMS devices — which is exactly what we're talking about in this episode!

cover

May 31Podcast

Stepping Into New Dimension With React Native VisionOS

Try immersing yourself in the React Universe with React Native visionOS! Listen about the latest changes in the framework & watch a 3D app demo.

cover

Mar 19Tutorial

The Hard Way vs. The React Native AI SDK Way: Stop Writing Custom Modules for Every Model

Learn how React Native AI uses a unified provider model to switch between cloud and on-device LLMs without rewriting application logic, enabling reliable AI experiences online and offline.

cover

Mar 12Tutorial

Build Smarter Apps: Tool Calling & AI Orchestration Explained

Learn how on-device models in React Native can call tools, interact with external APIs, and return structured outputs you can use directly in application logic.

cover

Mar 5Tutorial

MLC LLM + React Native: On-Device AI Without the Pain

Learn how to run third-party on-device LLMs in React Native using MLC LLM. Choose your models, run them efficiently across platforms, and keep a unified JavaScript API with React Native AI.

cover

Feb 24Tutorial

Intelligent Fallbacks with Apple Intelligence in React Native

Learn how to use Apple’s built-in Foundation Models in React Native apps, reduce memory usage, and enable fast, fully on-device AI with React Native AI Apple.

cover

Feb 10Tutorial

What Is the React Native AI SDK? A Complete Intro & Quickstart

Learn why on-device AI matters for React Native apps, how local LLMs behave offline, and what problems React Native AI is designed to solve from day one.

cover

Jan 29Tutorial

Implementing an Android TurboModule with Kotlin

Learn how to implement a React Native TurboModule on Android, from the TypeScript spec and Codegen to the Kotlin implementation and package registration.

cover

Jan 19Tutorial

Working with Different Threads in Swift TurboModules

Learn how JavaScript, native module, background, and main threads interact in React Native TurboModules, and how to use GCD queues to run async work safely in Swift.

cover

Jan 9Tutorial

How to Add Type-Safe Constants to Swift TurboModules

Learn how to expose typed, immutable constants from a Swift TurboModule using Codegen, and get full end-to-end type safety between native and JavaScript.

cover

Dec 30Tutorial

Adding Event Emitters to Your TurboModule in Swift

Learn how to emit native events from a Swift TurboModule and subscribe to them in JavaScript, including proper memory management and Codegen integration.

cover

Dec 22Tutorial

Writing Your First TurboModule in Swift

Learn how to build a fully working TurboModule in Swift, integrate it with Codegen, and bridge it through Objective‑C inside an Expo app.