What it is
JetBrains' extension of Jetpack Compose to desktop, iOS and web, letting one declarative UI codebase target several platforms.
Shared composables live in commonMain. Platform-specific behaviour is supplied through expect/actual declarations.
Installation
plugins { id("org.jetbrains.compose") version "1.7.0" }Getting started
The smallest useful thing you can do with it, and what each part means.
kotlin
// commonMain — runs everywhere
@Composable
fun App(viewModel: BookViewModel) {
MaterialTheme {
val state by viewModel.state.collectAsState()
BookList(state.books, onSelect = viewModel::select)
}
}
// commonMain — declare what each platform must provide
expect fun openUrl(url: String)
// androidMain
actual fun openUrl(url: String) {
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
}
// iosMain
actual fun openUrl(url: String) {
UIApplication.sharedApplication.openURL(NSURL(string = url))
}Advanced usage
Where the library earns its place over a simpler alternative.
kotlin
// desktopMain
fun main() = application {
Window(onCloseRequest = ::exitApplication, title = "Library") {
App(remember { BookViewModel() })
}
}
// iosMain — embedded in a SwiftUI view
fun MainViewController() = ComposeUIViewController { App(viewModel) }
// Adapt layout to the window, not the platform.
@Composable
fun AdaptiveLayout(windowSize: DpSize) {
if (windowSize.width > 840.dp) TwoPaneLayout() else SinglePaneLayout()
}Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- Expected declaration has no actual for target
- Every target needs an actual. Add one per source set, even if it throws NotImplementedError for now.
- A JVM-only library fails to resolve in commonMain
- commonMain can only use Multiplatform libraries. Move the usage to a platform source set behind expect/actual.
Best practices
- Share the layer beneath the UI first; sharing UI is the more ambitious step.
- Branch on window size, not on platform, so layouts adapt rather than fork.
- Expect a less mature iOS story than Android — test on device early.
- Keep platform APIs behind expect/actual rather than scattering conditionals.
Background
Why it exists, and what it was reacting to.
Compose Multiplatform takes Google's Android UI toolkit and renders it with Skia on other platforms, so the same composables run on Android, iOS, desktop JVM and the browser.
