Claude
Skills
Sign in
Back

kmp

Included with Lifetime
$97 forever

Kotlin Multiplatform fundamentals - use for project setup, expect/actual patterns, source sets, and platform-specific code

General

What this skill does


# Kotlin Multiplatform (KMP) Fundamentals

Kotlin Multiplatform enables sharing code across Android, iOS, Desktop, Web (WASM), and Server.

## Project Structure

### Multi-Module Architecture (Feature-based + api/impl)

```
your-project-admin/
├── build.gradle.kts              # Root build config
├── settings.gradle.kts           # Module includes
├── gradle/libs.versions.toml     # Version catalog
│
├── core/
│   ├── common/                   # Utilities, Result types, extensions
│   │   └── src/commonMain/kotlin/
│   ├── data/                     # Data abstractions, DataStore
│   │   ├── src/commonMain/kotlin/
│   │   ├── src/androidMain/kotlin/
│   │   └── src/iosMain/kotlin/
│   ├── database/                 # Room (Android/iOS/JVM only)
│   │   └── src/commonMain/kotlin/
│   ├── network/                  # Ktor client
│   │   └── src/commonMain/kotlin/
│   └── ui/                       # Design system, theme
│       └── src/commonMain/kotlin/
│
├── feature/
│   ├── auth/
│   │   ├── api/                  # Public interfaces, models
│   │   │   └── src/commonMain/kotlin/
│   │   └── impl/                 # Implementation, UI
│   │       └── src/commonMain/kotlin/
│   └── home/
│       ├── api/
│       └── impl/
│
├── composeApp/                   # Platform entry points
│   ├── src/commonMain/           # App composition, DI graph
│   ├── src/androidMain/          # MainActivity
│   ├── src/iosMain/              # iOS entry
│   ├── src/jvmMain/              # Desktop main()
│   └── src/wasmJsMain/           # Web entry
│
└── iosApp/                       # Xcode project
```

### Source Sets Hierarchy

```
commonMain
├── androidMain
├── iosMain
│   ├── iosX64Main
│   ├── iosArm64Main
│   └── iosSimulatorArm64Main
├── jvmMain
├── wasmJsMain
└── jsMain (fallback)
```

## Gradle Setup

### Root build.gradle.kts

```kotlin
plugins {
    alias(libs.plugins.kotlinMultiplatform) apply false
    alias(libs.plugins.androidApplication) apply false
    alias(libs.plugins.androidLibrary) apply false
    alias(libs.plugins.composeMultiplatform) apply false
    alias(libs.plugins.composeCompiler) apply false
    alias(libs.plugins.kotlinSerialization) apply false
    alias(libs.plugins.ksp) apply false
    alias(libs.plugins.room) apply false
    alias(libs.plugins.metro) apply false
}
```

### settings.gradle.kts

```kotlin
pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
    }
}

rootProject.name = "your-project-admin"

// Core modules
include(":core:common")
include(":core:data")
include(":core:database")
include(":core:network")
include(":core:ui")

// Feature modules
include(":feature:auth:api")
include(":feature:auth:impl")
include(":feature:home:api")
include(":feature:home:impl")

// App entry points
include(":composeApp")
```

### gradle/libs.versions.toml

```toml
[versions]
kotlin = "2.3.20"
agp = "9.1.0"
compose-multiplatform = "1.10.3"
ktor = "3.4.1"
room = "2.8.4"
datastore = "1.2.0"
decompose = "3.5.0"
metro = "0.10.2"
essenty = "2.5.0"
coroutines = "1.10.2"
serialization = "1.10.0"
ksp = "2.3.20-1.0.31"

[libraries]
# Kotlin
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" }

# Ktor
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" }
ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }

# Room (Android, iOS, JVM only)
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
androidx-sqlite-bundled = { module = "androidx.sqlite:sqlite-bundled", version = "2.6.2" }

# DataStore
datastore-preferences-core = { module = "androidx.datastore:datastore-preferences-core", version.ref = "datastore" }

# Decompose
decompose = { module = "com.arkivanov.decompose:decompose", version.ref = "decompose" }
decompose-compose = { module = "com.arkivanov.decompose:extensions-compose", version.ref = "decompose" }
essenty-lifecycle = { module = "com.arkivanov.essenty:lifecycle", version.ref = "essenty" }

[plugins]
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
androidApplication = { id = "com.android.application", version.ref = "agp" }
androidLibrary = { id = "com.android.library", version.ref = "agp" }
composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "compose-multiplatform" }
composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
room = { id = "androidx.room", version.ref = "room" }
metro = { id = "dev.zacsweers.metro", version.ref = "metro" }
```

### Module build.gradle.kts (KMP Library)

```kotlin
// core/common/build.gradle.kts
plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.androidLibrary)
}

kotlin {
    androidTarget {
        compilerOptions {
            jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21)
        }
    }

    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64()
    ).forEach { iosTarget ->
        iosTarget.binaries.framework {
            baseName = "CoreCommon"
            isStatic = true
        }
    }

    jvm("desktop")

    wasmJs {
        browser()
    }

    sourceSets {
        commonMain.dependencies {
            implementation(libs.kotlinx.coroutines.core)
        }

        androidMain.dependencies {
            // Android-specific
        }

        iosMain.dependencies {
            // iOS-specific
        }

        val desktopMain by getting {
            dependencies {
                // Desktop-specific
            }
        }
    }
}

android {
    namespace = "com.your-project.admin.core.common"
    compileSdk = 35

    defaultConfig {
        minSdk = 24
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_21
        targetCompatibility = JavaVersion.VERSION_21
    }
}
```

## expect/actual Pattern

### Declaration (commonMain)

```kotlin
// commonMain/kotlin/Platform.kt
expect class PlatformContext

expect fun getPlatformName(): String

expect fun createDataStorePath(context: PlatformContext): String
```

### Android Implementation

```kotlin
// androidMain/kotlin/Platform.android.kt
actual typealias PlatformContext = android.content.Context

actual fun getPlatformName(): String = "Android ${android.os.Build.VERSION.SDK_INT}"

actual fun createDataStorePath(context: PlatformContext): String {
    return context.filesDir.resolve("datastore").absolutePath
}
```

### iOS Implementation

```kotlin
// iosMain/kotlin/Platform.ios.kt
import platform.Foundation.NSDocumentDirectory
import platform.Foundation.NSFileManager
import platform.Foundation.NSUserDomainMask

actual class PlatformContext

actual fun getPlatformName(): String = "iOS"

actual fun createDataStorePath(context: PlatformContext): String {
    val documentDir = NSFileManager.defaultManager.URLForDirectory(
        NSDocumentDirectory,
        NSUserDomainMask,
        null,
        false,
        null
    )
    return "${documentDir?.path}/datastore"
}
```

### Desktop Implementation

```kotlin
// desktopMain/kotlin/Platform.jvm.kt
import java.io.File

actual class PlatformContext

actual fun getPla
Files: 1
Size: 16.1 KB
Complexity: 19/100
Category: General

Related in General