KMP Architecture Rules
Activate only if commonMain exists.
Hard Rules
- •No
android.*imports in commonMain — use expect/actual for platform APIs. - •No
java.timein commonMain — usekotlinx-datetime. - •No Android ViewModel in shared code — use StateHolder pattern.
- •No
Dispatchers.Mainhardcoded in commonMain — inject dispatchers. - •Use KSP for annotation processing — KAPT does not support multiplatform.
- •No
freeze()calls — the new Kotlin/Native memory model (default since 1.7.20) makes them unnecessary. - •Shared code must compile for all declared targets — never skip a target in CI.
Core Patterns
State Management
- •commonMain:
StateHolderclass exposesStateFlow<UiState>. - •androidMain:
ViewModelwrapsStateHolder, bridges to Android lifecycle. - •iosMain: Swift class holds
StateHolder, collects flows viaCancellableContinuationor SKIE/KMP-NativeCoroutines.
Dependency Injection
- •Use Koin Multiplatform or manual factory pattern in commonMain.
- •Platform modules provide platform-specific implementations via
actualdeclarations or Koin modules.
Source Set Hierarchy
- •Use hierarchical source sets (
appleMain,nativeMain,jvmMain) to share platform-adjacent code. - •
commonMain→jvmMain→androidMain/desktopMain. - •
commonMain→nativeMain→appleMain→iosMain/macosMain.
Kotlin 2.0+ Considerations
- •K2 compiler is default since Kotlin 2.0 — ensure libraries are K2-compatible.
- •Compose Compiler is now a Gradle plugin (
org.jetbrains.kotlin.plugin.compose) — not a separate compiler artifact.
References
- •references/project_structure.md
- •references/common_libraries.md
- •references/platform_apis.md
- •references/testing_kmp.md
- •references/dependency_injection.md