app-gradle-plugins
0.8.4indexedOpinionated Gradle plugins delivering sensible defaults for app modules: automatic namespace generation, Compose integration, DI and baseline-profile tooling, code formatting, and optimized build/test setup.
Opinionated Gradle plugins delivering sensible defaults for app modules: automatic namespace generation, Compose integration, DI and baseline-profile tooling, code formatting, and optimized build/test setup.
A collection of opinionated Gradle plugins for building Kotlin Multiplatform and Android projects with sensible defaults and minimal configuration. Compatible with AGP 9.0+.
Add to your gradle/libs.versions.toml:
[versions]
app-gradle-plugins = "0.1.1"
[plugins]
app-android = { id = "io.github.thomaskioko.gradle.plugins.android", version.ref = "app-gradle-plugins" }
app-app = { id = "io.github.thomaskioko.gradle.plugins.app", version.ref = "app-gradle-plugins" }
app-jvm = { id = "io.github.thomaskioko.gradle.plugins.jvm", version.ref = "app-gradle-plugins" }
app-multiplatform = { id = "io.github.thomaskioko.gradle.plugins.multiplatform", version.ref = "app-gradle-plugins" }
app-root = { id = "io.github.thomaskioko.gradle.plugins.root", version.ref = "app-gradle-plugins" }
app-spotless = { id = "io.github.thomaskioko.gradle.plugins.spotless", version.ref = "app-gradle-plugins" }
Then use in your build.gradle.kts:
plugins {
alias(libs.plugins.app.multiplatform)
}
plugins {
id("io.github.thomaskioko.gradle.plugins.multiplatform") version "0.1.1"
}
Apply io.github.thomaskioko.gradle.plugins.root to the root project's build.gradle.kts. This is required. Applying any other plugin in this suite (app, android, , , ) without on the root project throws a at apply-time.
// Root build.gradle.kts
plugins {
id("io.github.thomaskioko.gradle.plugins.root")
}
Configures a Kotlin Multiplatform module with default targets (Android, JVM, iOS) and sensible defaults. Uses com.android.kotlin.multiplatform.library for the Android target (AGP 9.0+).
Default targets provided: Android (via KMP Android library), JVM, iosArm64, iosSimulatorArm64.
plugins {
id("io.github.thomaskioko.gradle.plugins.multiplatform")
}
scaffold {
// Enable explicit API mode
explicitApi()
optIn(, )
addAndroidTarget(
enableAndroidResources = ,
withHostTestBuilder = ,
includeAndroidResources = ,
configure = {
useCompose()
minSdkVersion()
},
lintConfiguration = {
baseline = file()
disable +=
},
)
addIosTargetsWithXcFramework()
configureNativeTargets(bundleId = )
useSerialization()
useMetro()
}
addAndroidTarget ParametersFor Android library modules with automatic namespace configuration and optimized defaults. Applies com.android.library and configures build features, compile options, and test setup.
plugins {
id("io.github.thomaskioko.gradle.plugins.android")
}
scaffold {
android {
// Enable Compose support
useCompose()
// Enable build config generation
enableBuildConfig()
// Configure ProGuard consumer rules
consumerProguardFiles("consumer-rules.pro")
minSdkVersion()
useBaselineProfile()
useRoborazzi()
useManagedDevices(
deviceName = ,
device = ,
apiLevel =
)
libraryConfiguration {
}
}
}
For Android application modules with signing configuration and optimization. Automatically enables buildConfig.
plugins {
id("io.github.thomaskioko.gradle.plugins.app")
}
scaffold {
app {
// Set the application ID
applicationId("com.example.app")
// Configure build type suffixes
applicationIdSuffix("debug", ".debug")
// Enable minification for release builds
minify(
file("proguard-rules.pro"),
file("proguard-android-optimize.txt")
)
}
android {
// Enable Compose support
useCompose()
// Managed devices work for app projects too
useManagedDevices()
}
}
For benchmark modules that generate baseline profiles. Uses com.android.test plugin.
plugins {
id("io.github.thomaskioko.gradle.plugins.baseline-profile")
}
scaffold {
benchmark {
// Configure managed devices for baseline profile generation
useManagedDevices(
deviceName = "pixel6Api34",
device = "Pixel 6",
apiLevel = 34
)
}
}
For pure Kotlin/JVM modules.
plugins {
id("io.github.thomaskioko.gradle.plugins.jvm")
}
scaffold {
jvm {
// Enable Android Lint for JVM modules
useAndroidLint()
}
// Common configurations work here too
explicitApi()
useSerialization()
}
Configures the root project with dependency analysis, the aggregate test tasks (linuxTest, iosTest, ciTest), version checks, and common tooling. Required: must be applied on the root project before any other plugin in this suite. See Required Setup.
plugins {
id("io.github.thomaskioko.gradle.plugins.root")
}
Automatic code formatting with Spotless using Kotlin and KTX configurations.
plugins {
id("io.github.thomaskioko.gradle.plugins.spotless")
}
Layers a custom ktlint rule set on top of Spotless's standard checks. Apply once to the root project; the plugin propagates configuration to every subproject and applies Spotless transitively.
// Root build.gradle.kts
plugins {
alias(libs.plugins.app.root)
alias(libs.plugins.app.lint)
}
The plugin reads its own version from the JAR manifest's Implementation-Version attribute and resolves io.github.thomaskioko.gradle.plugins:lint-rules:<own-version> automatically. There is no version literal to maintain in consumer projects. Bumping app-gradle-plugins in libs.versions.toml automatically pulls the matching lint-rules artifact.
lint-rulesThe rules are TvManiac-specific. Other consumers of app-gradle-plugins are not forced into them: only projects that explicitly apply app.lint get the rules.
SpotlessPlugin reads the property via Project.findProperty(...), so values set programmatically (extras) and via -P flags also work.
Add to gradle.properties:
# Used to generate Android namespace based on module path
package.name=com.example
# Build Flags
app.debugOnly=true
app.enableIos=false
Required entries in libs.versions.toml:
The useCompose() configuration:
scaffold { android { useCompose() } } for Android/App pluginsaddAndroidTarget(configure = { useCompose() }) for KMP pluginBuilt-in support for Kotlin Inject and Metro:
useMetro() - Applies Metro plugin and adds runtime dependencyCopyright 2025 Thomas Kioko
Licensed under the Apache License, Version 2.0
jvmmultiplatformbaserootGradleException| Parameter | Type | Default | Description |
|---|
enableAndroidResources | Boolean | false | Enable Android resources for the KMP Android target |
withHostTestBuilder | Boolean | false | Enable host-side (JVM) unit tests for Android. Not compatible with some plugins (e.g., moko-resources) |
includeAndroidResources | Boolean | false | Include Android resources in unit tests (isIncludeAndroidResources) |
withDeviceTestBuilder | Boolean | false | Enable on-device instrumented tests |
withJava | Boolean | false | Enable Java interop for the Android target |
configure | AndroidExtension.() -> Unit | {} | Configure Android-specific options (Compose, minSdk, etc.) |
lintConfiguration | Lint.() -> Unit | {} | Configure lint rules for the Android target |
| Rule ID | Enforces |
|---|
tvmaniac:no-mutating-router-import | No com.arkivanov.decompose.router.{stack,slot}.* imports outside /navigation/ modules, except read-only ChildStack and ChildSlot types that render-site presenters and UIs need. |
tvmaniac:no-navigation-construct-outside-nav | No StackNavigation<>() / SlotNavigation<>() constructor calls outside /navigation/ modules. |
tvmaniac:no-custom-navigator-interface | No custom XxxNavigator interfaces. Only the canonical Navigator and SheetNavigator are allowed. |
tvmaniac:no-style-wrapper-in-preview | No TvManiacTheme { ... } or TvManiacBackground { ... } wrappers inside @Preview-family functions; the styling is applied automatically by TvManiacPreviewWrapperProvider. |
tvmaniac:test-name-format | @Test (and @ParameterizedTest, @RepeatedTest) functions must be named should X given Y or should X when Y (backticked) / shouldXGivenY (camelCase, used in src/androidTest). |
[versions]
# Compilation targets
java-target = "17"
java-toolchain = "17"
android-compile = "35"
android-min = "24"
android-target = "35"
[libraries]
# For Compose support
androidx-compose-compiler = { module = "androidx.compose.compiler:compiler", version = "..." }
# For serialization
kotlin-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version = "..." }
# For baseline profiles
androidx-profileinstaller = { module = "androidx.profileinstaller:profileinstaller", version = "..." }
# For desugaring (optional)
android-desugarJdkLibs = { module = "com.android.tools:desugar_jdk_libs", version = "..." }
:data:api becomes com.example.data.api)android-desugarJdkLibs is in the version catalogSurfaced from shared tags and platforms — no rankings paid for.