Skip to content

firdaus1453/TemplateKMP

Repository files navigation

🏗️ TemplateKMP

Production-ready Kotlin Multiplatform template with Clean Architecture

Kotlin Compose Multiplatform Platform License

A scalable, multi-module KMP/CMP template — ready to build your next cross-platform app.


✨ Features

  • 🎯 Multi-module Clean Architecture — Domain, Data, Presentation separation per feature
  • 🧩 Convention Plugins — 9 pre-built Gradle plugins for consistent module configuration
  • 🔐 Authentication Ready — Session storage, Bearer auth, auto token refresh via Ktor
  • 🎨 Design System — Centralized theme, typography, and reusable UI components
  • 📱 MVI Pattern — Unidirectional data flow with ViewModel + StateFlow
  • 🗄️ Room Database — Offline-first ready with convention plugin
  • 🧪 Testing Infrastructure — Unit tests with Turbine + Kover code coverage
  • 🌐 Ktor Networking — Type-safe HTTP client with error handling
  • 💉 Koin DI — Lightweight dependency injection across all platforms
  • 🖼️ Coil Image Loading — Multiplatform image loading and caching
  • 🔧 BuildKonfig — Secure build-time constants from local.properties

🏛️ Architecture

TemplateKMP/
├── 🔧 build-logic/convention/         # 9 Gradle convention plugins
├── 📱 composeApp/                      # Composition root (Android, iOS, Desktop)
├── 🏗️ core/
│   ├── domain/                         # Pure Kotlin: Result, DataError, interfaces
│   ├── data/                           # Ktor, DataStore, SessionStorage
│   ├── presentation/                   # UiText, shared composables
│   └── designsystem/                   # AppTheme, colors, typography
├── 🧩 feature/
│   ├── auth/        (domain, presentation)
│   ├── home/        (domain, data, presentation)
│   ├── profile/     (domain, data, presentation)
│   ├── settings/    (domain, data, presentation)
│   ├── search/      (domain, data, presentation)
│   ├── notifications/ (domain, presentation)     # stub
│   └── media/       (domain, presentation)        # stub
├── 📄 gradle/libs.versions.toml
└── ⚙️ settings.gradle.kts

Dependency Rules

composeApp → core/* + feature/*/
feature/*/presentation → feature/*/domain + core/presentation + core/designsystem
feature/*/data → feature/*/domain + core/domain + core/data
core/data → core/domain
core/presentation → core/domain + core/designsystem

Key Principles:

  • domain = pure Kotlin, ZERO framework imports
  • data implements domain interfaces
  • presentation depends on domain only, never on data
  • Feature modules NEVER depend on other feature modules
  • composeApp wires all DI and navigation

🔧 Convention Plugins

Plugin ID Purpose
KmpLibraryConventionPlugin template.kmp.library Pure Kotlin Multiplatform library module
CmpLibraryConventionPlugin template.cmp.library Compose Multiplatform library module
CmpFeatureConventionPlugin template.cmp.feature Feature presentation module (Compose + ViewModel)
CmpApplicationConventionPlugin template.cmp.application Main app module (Android + iOS + Desktop)
AndroidApplicationConventionPlugin template.android.application Android application base config
AndroidApplicationComposeConventionPlugin template.android.application.compose Android Compose integration
KoverConventionPlugin template.kover Kover test coverage reporting
RoomConventionPlugin template.room Room database with KSP
BuildKonfigConventionPlugin template.buildkonfig Build-time constants from local.properties

🛠️ Tech Stack

Technology Version Purpose
Kotlin 2.3.0 Language
Compose Multiplatform 1.10.0 UI framework
Koin 4.1.0 Dependency injection
Ktor 3.2.3 HTTP client
Room 2.7.2 Database (offline-first)
Navigation Compose 2.9.0 Navigation
DataStore 1.1.7 Session storage
Coil 3.3.0 Image loading
Kover 0.9.1 Test coverage
Turbine 1.2.0 Flow testing
Kermit 2.0.6 Multiplatform logging
BuildKonfig 0.17.1 Build constants
Chucker 4.1.0 HTTP debugging (Android)

📖 Developer Guide

New to this template? Check out our comprehensive Developer Guide (GUIDE.md) — a step-by-step tutorial for junior developers covering everything from environment setup to production release.


🚀 Getting Started

Prerequisites

  • Android Studio Ladybug or later (or IntelliJ IDEA with KMP plugin)
  • JDK 17+
  • Xcode 15+ (for iOS targets)

Clone & Build

git clone https://github.com/firdaus1453/TemplateKMP.git
cd TemplateKMP
./gradlew assemble

Run via CLI

📱 Android
# 1. Build debug APK
./gradlew :composeApp:assembleDebug

# 2. Install to connected device/emulator
adb install composeApp/build/outputs/apk/debug/composeApp-debug.apk

# 3. Launch the app
adb shell am start -n com.template.project/.MainActivity

Prerequisites:

  • Emulator running (adb devices to verify) or physical device connected with USB debugging enabled.
  • adb available in PATH (included with Android SDK platform-tools).
🖥️ Desktop (JVM)
# Run directly (opens desktop window)
./gradlew :composeApp:run

To create a native distributable (installer):

# macOS → .dmg | Windows → .msi | Linux → .deb
./gradlew :composeApp:createDistributable

Output location: composeApp/build/compose/binaries/

🍎 iOS (macOS only)

Option 1 — Xcode (Recommended):

Open iosApp/iosApp.xcodeproj in Xcode, select a simulator, and click ▶ Run.

Option 2 — CLI:

# 1. List available simulators (find your device name)
xcrun simctl list devices available

# 2. Boot simulator (if not already running)
xcrun simctl boot "iPhone 16"

# 3. Build the project
xcodebuild -project iosApp/iosApp.xcodeproj -scheme iosApp \
  -destination 'platform=iOS Simulator,name=iPhone 16' \
  -configuration Debug build

# 4. Install on booted simulator
xcrun simctl install booted \
  ~/Library/Developer/Xcode/DerivedData/iosApp-*/Build/Products/Debug-iphonesimulator/TemplateKmp.app

# 5. Launch
xcrun simctl launch booted com.template.project.TemplateKmp

Prerequisites:

  • macOS with Xcode 15+ and Command Line Tools (xcode-select --install).
  • First build will be slow due to Kotlin/Native compilation.
  • If "No matching destination" error appears, check that IPHONEOS_DEPLOYMENT_TARGET ≤ your simulator's iOS version.

📁 Adding a New Feature Module

  1. Add module entries to settings.gradle.kts:

    include(":feature:yourfeature:domain")
    include(":feature:yourfeature:data")
    include(":feature:yourfeature:presentation")
  2. Create each module with the appropriate convention plugin:

    // feature/yourfeature/domain/build.gradle.kts
    plugins {
        alias(libs.plugins.convention.kmp.library)
        alias(libs.plugins.convention.kover)
    }
    
    // feature/yourfeature/data/build.gradle.kts
    plugins {
        alias(libs.plugins.convention.kmp.library)
        alias(libs.plugins.convention.kover)
    }
    
    // feature/yourfeature/presentation/build.gradle.kts
    plugins {
        alias(libs.plugins.convention.cmp.feature)
        alias(libs.plugins.convention.kover)
    }
  3. Follow the MVI pattern:

    • Domain: Models + Repository interface (pure Kotlin)
    • Data: Repository implementation (Ktor/Room)
    • Presentation: ViewModel (State, Action, Event) + Composable Screens
  4. Register DI module in composeApp and add navigation route


🧪 Testing

# Run all tests
./gradlew allTests

# Generate coverage report
./gradlew koverHtmlReport

# Verify coverage threshold
./gradlew koverVerify

Each feature module includes:

  • Fake repositories for unit testing
  • ViewModel tests using Turbine for Flow assertions
  • Kover integration for code coverage reporting

📋 Project Conventions

Convention Rule
Naming Default*Repository, *ViewModel, *Screen, *State, *Action, *Event
DI One Koin module per feature, registered in composeApp
Navigation @Serializable data objects/classes as routes
Error handling Result<D, E> sealed interface — never throw exceptions
Logging Kermit only — never println() or Log.d()
Secrets local.properties + BuildKonfig — never commit API keys
State management SharingStarted.WhileSubscribed(5_000) for UI state

🤝 Contributing

Contributions are welcome! Feel free to open issues or submit pull requests.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'feat: add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

MIT License

Copyright (c) 2025 Muhammad Firdaus

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

About

Production-ready Kotlin Multiplatform template with multi-module Clean Architecture — Android, iOS, Desktop

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors