Skip to content

vishrayne/cmp-clean-starter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

8 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Compose Multiplatform Clean Architecture Template

A modern, production-ready Compose Multiplatform project template with clean architecture, dependency injection, code quality tools, and AGP 9 compatible configuration for Android and iOS.

Kotlin Compose Multiplatform AGP kotlin-inject Spotless

✨ What Makes This Template Special?

This template solves a critical issue with the default Kotlin Multiplatform wizard and provides a * production-ready* foundation with enterprise-grade tooling:

The Problem with Default Templates

The standard KMP wizard generates projects that combine kotlinMultiplatform and androidApplication plugins in a single module, which triggers deprecation warnings that will break with Android Gradle Plugin 9.0.0+.

This Template's Solution

βœ… Proper separation: Shared KMP code in dedicated modules
βœ… Modern plugin: Uses com.android.kotlin.multiplatform.library
βœ… Clean architecture: Clear boundaries between shared and platform code
βœ… Dependency Injection: kotlin-inject + kotlin-inject-anvil for compile-safe DI
βœ… Design System: Dedicated module for shared UI components and theming
βœ… Code Quality: Spotless + ktlint + Compose lints pre-configured
βœ… No warnings: Future-proof for AGP 9.0.0+
βœ… Production-ready: Battle-tested structure for real-world apps

πŸ—οΈ Project Structure

your-app-name/
β”œβ”€β”€ shared/                          # Core business logic & utilities
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ commonMain/             # Shared code (Platform, Greeting, DI)
β”‚   β”‚   β”œβ”€β”€ androidMain/            # Android-specific implementations
β”‚   β”‚   └── iosMain/                # iOS-specific implementations
β”‚   └── build.gradle.kts            # Uses androidKotlinMultiplatformLibrary plugin
β”‚
β”œβ”€β”€ designsystem/                    # Shared UI Design System
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ commonMain/
β”‚   β”‚   β”‚   └── kotlin/
β”‚   β”‚   β”‚       └── designsystem/
β”‚   β”‚   β”‚           β”œβ”€β”€ Button.kt   # Reusable UI components
β”‚   β”‚   β”‚           └── theme/      # Theme, Colors, Typography
β”‚   β”‚   β”œβ”€β”€ androidMain/            # Android-specific theme impl
β”‚   β”‚   └── iosMain/                # iOS-specific theme impl
β”‚   └── build.gradle.kts            # Shared design system module
β”‚
β”œβ”€β”€ androidApp/                      # Pure Android application module
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ main/
β”‚   β”‚   β”‚   β”œβ”€β”€ kotlin/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ MainActivity.kt
β”‚   β”‚   β”‚   β”‚   └── YourNameApplication.kt  # DI setup
β”‚   β”‚   β”‚   β”œβ”€β”€ AndroidManifest.xml
β”‚   β”‚   β”‚   └── res/                # App icon, strings, etc.
β”‚   β”‚   β”œβ”€β”€ test/                   # Unit tests
β”‚   β”‚   └── androidTest/            # Instrumentation tests
β”‚   └── build.gradle.kts            # Pure Android app configuration
β”‚
β”œβ”€β”€ iosApp/                          # iOS application
β”‚   β”œβ”€β”€ iosApp/
β”‚   β”‚   β”œβ”€β”€ ContentView.swift
β”‚   β”‚   └── iOSApp.swift
β”‚   └── iosApp.xcodeproj
β”‚
β”œβ”€β”€ gradle/
β”‚   └── libs.versions.toml          # Centralized dependency management
β”œβ”€β”€ build.gradle.kts                # Root build with Spotless config
β”œβ”€β”€ settings.gradle.kts             # Module configuration
└── .editorconfig                   # Code style configuration

πŸš€ Getting Started

Prerequisites

  • Android Studio Koala (2024.1.1) or later
  • JDK 17 or later
  • Xcode 15.0+ (for iOS development)
  • CocoaPods (for iOS dependencies, if needed)

Using This Template

Option 1: GitHub Template (Recommended)

  1. Click "Use this template" button at the top of this repository
  2. Create your new repository
  3. Clone it locally
  4. Follow the Renaming Instructions

Option 2: Manual Clone

git clone https://github.com/yourusername/cmp-clean-starter.git MyAwesomeApp
cd MyAwesomeApp
# Follow RENAMING.md guide

First Build

# Format code with Spotless
./gradlew spotlessApply

# Build for all platforms
./gradlew build

# Run Android app
./gradlew :androidApp:installDebug

# Build iOS framework
./gradlew :shared:assembleSharedDebugXCFramework
# Then open iosApp/iosApp.xcodeproj in Xcode and run

πŸ“ Renaming the Project

See the detailed RENAMING.md guide for step-by-step instructions on customizing this template for your project. The guide covers:

  • Updating package names across all modules
  • Renaming theme and typography
  • Updating Application class name
  • iOS bundle identifier changes

🎯 Key Features

Multi-Module Architecture

  • shared/: Core business logic, platform abstractions, dependency injection setup
  • designsystem/: Reusable UI components, theming system, typography
  • androidApp/: Android application entry point with custom Application class
  • iosApp/: iOS application with SwiftUI

Dependency Injection (kotlin-inject)

  • Compile-safe DI: No reflection, all checks at compile time
  • kotlin-inject-anvil: Automatic component merging across modules
  • Scoped components: AndroidAppComponent, IosAppComponent, shared AppComponent
  • Example setup included: See YourNameApplication.kt and DI package structure

Design System Module

  • Shared theming: Material3 theme with platform-specific implementations
  • Custom components: Ability to provide platform specific components with expect/actual implementations

Code Quality Tools

Spotless + ktlint

  • Automatic code formatting on build
  • Consistent style across team
  • Pre-configured with sensible defaults (feel free to change this!)
  • Run manually: ./gradlew spotlessApply

Compose Lints

  • Slack Compose Lint Checks: Android Lint-based rules for Compose
  • Compose Rules: ktlint-based rules integrated with Spotless
  • Catches common Compose mistakes at build time
  • Enforces best practices automatically

Latest KMP Plugin

  • androidKotlinMultiplatformLibrary: Official plugin from Google
  • No deprecation warnings: Ready for AGP 9.0.0+
  • Optimized for KMP: Better IDE support and build performance

πŸ› οΈ Technology Stack

Component Version Purpose
Kotlin 2.3.0 Programming language
Compose Multiplatform 1.9.3 UI framework
Android Gradle Plugin 8.11.2 Android build system
kotlin-inject 0.9.0 Compile-safe dependency injection
kotlin-inject-anvil 0.1.6 Component merging for multi-module DI
KSP 2.3.4 Kotlin Symbol Processing
Spotless 8.1.0 Code formatting
ktlint (via Spotless) Kotlin linter
Compose Lints 1.4.2 Slack's Compose lint checks
Compose Rules 0.4.26 ktlint Compose rules
Android Target SDK 36 Android API level
Android Min SDK 24 Android 7.0+ support

πŸ“š What's Included

Dependencies

  • βœ… Compose Multiplatform (Material3, Foundation, Resources)
  • βœ… kotlin-inject runtime & compiler
  • βœ… kotlin-inject-anvil for multi-module DI
  • βœ… Spotless with ktlint and Compose rules
  • βœ… Slack Compose Lint checks
  • βœ… Kotlin Test framework

Configuration

  • βœ… Gradle version catalogs (type-safe dependencies)
  • βœ… KSP for compile-time code generation
  • βœ… Proper JVM target configuration (Java 11)
  • βœ… Multi-module dependency injection setup
  • βœ… Automated code formatting on build
  • βœ… Compose best practices enforcement

🎨 Customization

Adding Dependencies

Dependencies are managed in gradle/libs.versions.toml:

[versions]
ktor = "3.0.0"

[libraries]
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }

[plugins]
kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }

Then use in module build.gradle.kts:

sourceSets {
    commonMain.dependencies {
        implementation(libs.ktor.client.core)
    }
}

Using Dependency Injection

1. Define an injectable class in shared:

@Inject
class GreetingService(private val platform: Platform) {
    fun greet(): String = "Hello from ${platform.name}!"
}

2. Add to component:

@ContributesTo(AppScope::class)
interface GreetingComponent {
    val greetingService: GreetingService
}

3. Use in Android:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val app = application as YourNameApplication
        val greeting = app.component.greetingService.greet()

        setContent {
            YourAppTheme {
                Text(greeting)
            }
        }
    }
}

Customizing the Design System

Update theme colors in designsystem/src/commonMain/kotlin/designsystem/theme/Color.kt:

val md_theme_light_primary = Color(0xFF6750A4)
val md_theme_light_onPrimary = Color(0xFFFFFFFF)
// ... customize all colors

Update typography in Theme.kt:

val YourAppTypography = Typography(
    displayLarge = TextStyle(
        fontFamily = YourCustomFont,
        fontWeight = FontWeight.Bold,
        fontSize = 57.sp,
    ),
    // ... customize all text styles
)

Running Code Quality Checks

# Format all code
./gradlew spotlessApply

# Check formatting without changes
./gradlew spotlessCheck

# Run all lints
./gradlew lint

# Run tests
./gradlew test

Adding New Platforms

To add desktop support:

1. Update shared/build.gradle.kts:

jvm("desktop")

2. Add desktop source set:

val desktopMain by getting {
    dependencies {
        implementation(compose.desktop.currentOs)
    }
}

3. Create desktop app module or add desktop-specific code

πŸ› Troubleshooting

"Unresolved reference: Res"

Solution: Check imports use the correct package:

import com.yourcompany.yourapp.shared.resources.Res

iOS Framework Not Found

Solution:

./gradlew clean
./gradlew :shared:assembleSharedDebugXCFramework

Then rebuild in Xcode.

Spotless Formatting Fails

Solution:

./gradlew spotlessApply

This will auto-fix most formatting issues.

KSP Generated Code Not Found

Solution: Clean and rebuild:

./gradlew clean
./gradlew :shared:kspCommonMainKotlinMetadata
./gradlew build

Dependency Injection Component Not Generated

Solution: Check that:

  1. KSP plugin is applied to the module
  2. kotlin-inject dependencies are in commonMain
  3. @Inject and @ContributesTo annotations are used correctly
  4. Rebuild the project

πŸ“– Learn More

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Areas for Contribution

  • Desktop platform support
  • Web (Wasm) platform support
  • Navigation library integration
  • Network layer example (Ktor/Apollo-Kotlin)
  • Local database example (SQLDelight/Room)
  • CI/CD configuration (GitHub Actions)
  • Documentation improvements

πŸ“„ License

This template is available under the MIT License. See LICENSE for details.

πŸ™ Acknowledgments

This template was created to address the deprecation warnings in the default Kotlin Multiplatform wizard and to provide a production-ready starting point with modern tooling. It follows official recommendations from:

Special thanks to:

  • JetBrains for Compose Multiplatform and Kotlin
  • Google for Android tooling and active development of Compose
  • Evan Tatarka for kotlin-inject
  • Amazon for kotlin-inject-anvil
  • Slack for Compose Lint Checks
  • Anthropic for Claude, which assisted in the design and documentation of this template

πŸ’¬ Support


Star ⭐ this repository if you find it useful!

Made with ❀️ for the Kotlin Multiplatform community

About

Compose Multiplatform project template compatible with AGP 9.0

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors