All Journal Notes

Ship Android, iOS & Web Apps in Days with Compose Multiplatform: The Ultimate GTM Stack

Why Kotlin Multiplatform and Compose Multiplatform are replacing Flutter and React Native for zero-to-one product velocity with single-language native performance.

For the past decade, building a modern multi-platform application meant choosing between painful tradeoffs:

1. Native Silos (Swift + Kotlin): Best performance and platform fidelity, but requires double the engineering headcount, separate codebases, and desynchronized product features. 2. React Native: Unified JavaScript/TypeScript ecosystem, but plagued by bridge serialization overhead, Hermes memory constraints, and fragile third-party native wrappers. 3. Flutter: Excellent 60 FPS Skia rendering, but locked into Google’s Dart language with an ecosystem disconnected from mainstream backend and enterprise tooling.

Enter Compose Multiplatform (CMP) powered by Kotlin Multiplatform (KMP).

By combining the declarative elegance of Jetpack Compose with the Google Skia graphics engine and compiling directly to native ARM64 binaries via Kotlin/Native LLVM, CMP has quietly become the ultimate zero-to-one Go-to-Market (GTM) stack.

Here is why we use it and how you can ship iOS, Android, and Web applications in days from a single repository.

---

1. The Single-Language Advantage: True 100% Code Sharing

In traditional cross-platform frameworks, "code sharing" often stops at business logic. With Compose Multiplatform, you share everything:

Domain & Data Models: Serialized with Kotlinx.serialization. Reactive State Machines: Modeled cleanly with Kotlin Coroutines and StateFlow. Networking & Persistence: Powered by Ktor HTTP client and SQLDelight/Room. UI Layouts & Components: The identical declarative Compose hierarchy renders across Android, iOS, Desktop (macOS/Linux/Windows), and Web (WebAssembly).

code
   ┌──────────────────────────────────────────────┐
   │            Compose Multiplatform UI          │
   ├──────────────────────────────────────────────┤
   │     MVI StateFlow / ViewModels / Actions     │
   ├──────────────────────────────────────────────┤
   │   Ktor HTTP  │  SQLDelight DB  │  Domain Logic│
   └──────┬──────────────────────┬──────────────┬─┘
          ▼                      ▼              ▼
     [ Android ]              [ iOS ]        [ Web ]
   (JVM Bytecode)          (LLVM Native)     (Wasm)

---

2. The Power of expect / actual

When building mobile applications, you inevitably need access to platform-specific hardware capabilities: biometric authentication, the iOS Keychain, camera sensors, or push notification tokens.

Instead of writing cumbersome native bridge plugins (like in React Native), Kotlin provides the compile-time expect / actual language primitive.

#### 1. Define the Common Expectation in commonMain:

kotlin
expect class SecureVault {
    suspend fun storeSecret(key: String, value: String)
    suspend fun retrieveSecret(key: String): String?
}

#### 2. Implement the iOS Version in iosMain using Apple Keychain:

kotlin
import platform.Security.*

actual class SecureVault {
    actual suspend fun storeSecret(key: String, value: String) {
        // Direct zero-overhead interop with Apple Security framework
        val query = CFDictionaryCreateMutable(...)
        SecItemAdd(query, null)
    }
    actual suspend fun retrieveSecret(key: String): String? {
        // Retrieve directly from Apple Keychain
        return null
    }
}

#### 3. Implement the Android Version in androidMain using Android Keystore:

kotlin
import androidx.security.crypto.EncryptedSharedPreferences

actual class SecureVault actual constructor(private val context: Context) {
    actual suspend fun storeSecret(key: String, value: String) {
        val prefs = EncryptedSharedPreferences.create(...)
        prefs.edit().putString(key, value).apply()
    }
}

Because this interop happens at compile time, there is zero JSON serialization, zero thread context hopping, and zero runtime performance penalty.

---

3. Native Rendering via Skia on iOS

A common complaint about non-native mobile apps is that they feel sluggish or exhibit touch jank.

On iOS, Compose Multiplatform uses the same Skia 2D graphics engine that powers Google Chrome, Android, and Flutter. CMP draws directly to an iOS Metal surface. The frame rate locks to 60 FPS (or 120 FPS on Apple ProMotion displays), delivering butter-smooth gestures, spring physics, and complex transitions.

---

4. The Web Target: WebAssembly (Wasm)

One of the most thrilling advancements in Kotlin 2.0+ is direct compilation to WebAssembly (Wasm/WASI).

Instead of transpiling Kotlin code into bloated JavaScript, Compose Multiplatform compiles to binary Wasm bytecode. In modern browsers (Chrome, Safari, Firefox), your exact native mobile UI runs inside an HTML5 <canvas> element with hardware acceleration and instant load times.

---

5. The 7-Day GTM Playbook

When launching a new startup product, time is your most precious resource. Managing three codebases (iOS, Android, Web) slows your learning loop by a factor of three.

With Compose Multiplatform: 1. Day 1–2: Scaffold the project using Compose Multiplatform Wizard. Define your shared UI design system and typography tokens. 2. Day 3–4: Implement backend REST/GraphQL client with Ktor and local cache with SQLDelight. 3. Day 5: Wire up expect/actual implementations for biometrics and notifications. 4. Day 6: Test simultaneously on iOS Simulator and Android Emulator with Compose Previews. 5. Day 7: Build release binaries and submit to Apple App Store, Google Play Store, and deploy Web Wasm build to Vercel/Cloudflare Pages.

Conclusion

Compose Multiplatform is not a compromise; it is an unfair competitive advantage for agile teams who care deeply about craft, speed, and clean code architecture.

UG

Umesh Gupta

@umesh

Founder & Software Architect

Founder of Abeta. Software architect focusing on high-throughput distributed state, authorization engines, and @abeta.dev/react-libs. Writing on Medium @adroitexplorer.

View all articles by Umesh Gupta