Hi everyone. It's been a while, a long, long while. I haven't published a blog in what feels like forever.
Honestly, it's not that I stopped writing. I just kept feeling like what I had wasn't quite ready to put out. So here we are, finally breaking that streak.
If you don't know already, I've started a new venture: Mobrio Studio, where I'm building FretPractice. It's built on Compose Multiplatform, and I figured writing about that platform choice might add some value to the community.
If you know me, you might think that's an obvious answer, I'm pretty loud about KMP. But trust me, it wasn't that straightforward. Read on.
My Take on Kotlin, KMP, and Compose Multiplatform
Kotlin
I've been a Kotlin advocate for a long time. Wrote books on it 8 years ago, and more than half my blog posts are Kotlin-related in some way. Safe to say I'm a fan, you wouldn't be wrong to call it love.
Kotlin Multiplatform
Same story here. When it comes to sharing business logic across platforms, KMP has no real competition. No other technology lets you write code in one language and ship it natively, compiled to native binaries, as libraries across platforms. Yes, you can do something similar with C++ or even Rust via FFI, but the added complexity only makes sense when you need low-level control for performance or security. For regular business logic sharing, KMP is the best choice, full stop.
One honest caveat though: KMP has a steep learning curve for production apps. If you're going this route, make sure you have a senior engineer on the team who actually knows the ropes.
Compose Multiplatform
Here's where things get nuanced.
I love Compose as an Android developer, it makes life genuinely easier. Yes, it has its quirks, and understanding Declarative UI takes some time to click, but once it does, Compose is great. And the Android team keeps improving it (keep an eye on Compose Styles if you haven't already).
That said, I've always had a strong preference for native UIs. Native means fewer platform-check conditionals cluttering your UI logic, a more intuitive feel per platform, and better performance.
Here's the thing about Compose Multiplatform: while KMP compiles to native binaries (LLVM on iOS/macOS, JVM bytecode on Android, minified JS on web), Compose Multiplatform can't do the same, it has to handle drawing itself (note, your app still does compile to native binaries, it just now has an added engine to draw ui). On iOS, for example, SwiftUI talks directly to Core Animation and Metal. Compose Multiplatform has to go through Skiko first, which then delegates to Metal. That extra layer isn't free, it costs performance.
The tradeoffs get broader as you add more target platforms. On Web with Wasm/JS, you give up standard web features like per-screen URLs and SEO. On Desktop, you're no longer shipping a native app per platform, you're shipping a JVM app.
So no, I've never been as enthusiastic about Compose Multiplatform as I am about Kotlin or KMP. My position on shared UI has always been skeptical.
Flutter
Contrary to what some might expect, I actually like Flutter. It lets you move fast, and for most apps that don't have heavy native dependencies, it's a solid choice. The learning curve is short and intuitive regardless of your background, that's genuinely hard to replicate.
If someone asks me to pick between Flutter and Compose Multiplatform for a standard CRUD app with no special constraints, I'd probably go Flutter. Even with my feelings about Dart.
So Why Compose Multiplatform for FretPractice?
The short answer: it's still the best fit for where I am right now, one developer, moving fast, building something that needs to ship.
But here's why it's not a simple answer.
FretPractice isn't just another focus or practice timer app. It's a music app. It needs DSP logic to accurately detect notes in real time. It'll have DRM for AI-generated music. It'll include DAW features - stem splitting, editing, production. And down the line, it needs to talk to hardware over Bluetooth and Wi-Fi.
That rules out Flutter entirely. The native dependencies are too deep.
But building fully native UIs for 8 platforms (Android, iOS, JVM Desktop, Web, watchOS, Wear OS, Android TV, Apple TV), is simply not feasible for a solo developer trying to actually launch something. So Compose Multiplatform is the pragmatic next-best choice.
Despite all the tradeoffs I laid out, it still inherits KMP's biggest strength: wiring in native code while sharing business logic efficiently. And the one KMP learning-curve caveat I mentioned? Doesn't apply when you're the one building it.
Also worth noting: if you structure your project well, replacing Compose Multiplatform UI with native UI later, while keeping the shared KMP logic intact is a much smaller lift than rewriting the whole thing from scratch.
That's the bet I'm making.
And that's really the point of this post, the "right" platform choice doesn't exist in a vacuum. It depends on what you're building, who's building it, and what constraints you're working within. If you're building a CRUD app solo and need to ship fast, maybe Flutter is your answer. If you have a team and the time, maybe full native is worth it. For me, right now, with FretPractice, Compose Multiplatform is the call that makes sense.
Anyway, it feels good to be writing again. I've got a lot more to share as FretPractice takes shape, the architecture decisions, the DSP work, the multiplatform quirks I run into along the way. If any of that sounds interesting, stick around.



Comments