Publish Kotlin Multiplatform Applications with Conveyor
This guide outlines a real-world configuration for publishing a Kotlin Multiplatform application with Hydraulic Conveyor.
For this tutorial, I am using maxDEV — a cross-platform (supports Mac, Windows, Linux) developer productivity app as an example.
Conveyor configuration
conveyor.conf:
include required("https://raw.githubusercontent.com/hydraulic-software/conveyor/master/configs/jvm/extract-native-libraries.conf")
include "/stdlib/jdk/17/amazon.conf"
app {
fsname = maxdev
display-name = maxDEV
updates = aggressive
icons = "icons/icon.png"
windows.icons = "icons/icon.ico"
mac.notarization {
app-specific-password = "!!!!-!!!!-!!!!-!!!"
}
jvm.extract-native-libraries = true
site.base-url = "https://kenanbek.github.io/maxDEV/download.html"
site.github.oauth-token = "!!!"
site.github.pages-branch = "gh-pages"
}
conveyor.compatibility-level = 17
conveyor.billing-email = "!!!"
conveyor.license-key = "!!!"
For Apple notarization, check this link.
For the Conveyor license key and billing, you need a Hydraulic subscription.
Gradle configuraitons
libs.versions:
[versions]
kotlin = "2.1.10"
kotlinx-coroutines = "1.10.1"
compose-multiplatform = "1.7.0"
androidx-lifecycle = "2.8.4"
junit = "4.13.2"
ktor = "3.1.1"
logback = "1.5.17"
ktlint-gradle = "11.6.1"
ktlint-ruleset-compose = "0.4.22"
conveyor = "1.12"
[plugins]
conveyor = { id = "dev.hydraulic.conveyor", version.ref = "conveyor" }
build.gradle.kts (root):
plugins {
alias(libs.plugins.conveyor) apply false
}
build.gradle.kts (desktop app):
plugins {
alias(libs.plugins.conveyor)
}
compose.desktop {
application {
mainClass = "com.appbaza.maxdev.MainKt"
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Exe, TargetFormat.Msi, TargetFormat.Deb, TargetFormat.Rpm)
packageName = "com.appbaza.maxdev"
packageVersion = "1.0.0"
macOS {
bundleID = "com.appbaza.maxdev"
signing {
sign.set(true)
identity.set("!!!")
}
notarization {
appleID.set("!!!")
password.set("!!!")
teamID.set("!!!")
}
}
}
}
}
Updates
I configured the application to GitHub Pages website for distributing updates. For manual updates, I am including a static page on the application's website.
Conveyor also supports other options.
At the current state of the project, I am using the aggressive update mode. Once the app reaches a more stable phase, I might consider the background update mode.
You can read more about update modes here.
Configuring the update mode is as easy as the following configuration in your conveyor.conf:
app {
fsname = maxdev
display-name = maxDEV
updates = aggressive
}
This is another excellent documentation from Hydraulic about updates in general:

Release
I use the following procedure for preparing a new release for maxDEV:
- Finalize code changes.
- Bump the version number in build.gradle.kts (:composeApp)
- Prepare package (
./gradlew clean package
) - Prepare download assets (
conveyor make site
) - Upload site (
conveyor make copied-site
)
You can reach out to me if you need consultancy and development support for your Kotlin cross-platform desktop projects: send an email to KEN at AppBaza.com.