name: kmp-architecture-best-practices description: Kotlin Multiplatform clean architecture enforcement. user-invocable: true
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