Skip to content

Getting Started

Prerequisites

Nucleus uses electron-builder under the hood to produce platform-specific installers (DMG, NSIS, DEB, RPM, AppImage, etc.). This requires Node.js 18+ and npm installed on your build machine.

# Verify your installation
node --version   # v18.0.0 or later
npm --version

CI/CD

The setup-nucleus composite action installs Node.js automatically. See CI/CD for details.

Installation

Add the Nucleus plugin to your build.gradle.kts:

plugins {
    id("io.github.kdroidfilter.nucleus") version "<version>"
}

The plugin is available on the Gradle Plugin Portal. No additional repository configuration is needed.

Runtime Libraries (Optional)

Runtime libraries are published on Maven Central:

dependencies {
    implementation(compose.desktop.currentOs)

    // Executable type detection + single instance + deep links
    implementation("io.github.kdroidfilter:nucleus.core-runtime:<version>")

    // AOT cache runtime detection (includes core-runtime)
    implementation("io.github.kdroidfilter:nucleus.aot-runtime:<version>")

    // Auto-update library (includes core-runtime)
    implementation("io.github.kdroidfilter:nucleus.updater-runtime:<version>")

    // Native taskbar/dock progress bar
    implementation("io.github.kdroidfilter:nucleus.taskbar-progress:<version>")

    // Custom decorated window with native title bar
    implementation("io.github.kdroidfilter:nucleus.decorated-window:<version>")
}

Minimal Configuration

nucleus.application {
    mainClass = "com.example.MainKt"

    nativeDistributions {
        targetFormats(TargetFormat.Dmg, TargetFormat.Nsis, TargetFormat.Deb)
        packageName = "MyApp"
        packageVersion = "1.0.0"
    }
}

Gradle Tasks

Development

Task Description
run Run the application from the IDE/terminal
runDistributable Run the packaged application image

Compose Hot Reload

Nucleus is fully compatible with Compose Hot Reload. Since Nucleus extends the Compose plugin (not replaces it), Hot Reload works out of the box.

The hotRun task reads mainClass from the compose.desktop.application block. If you only set it in nucleus.application, add a minimal Compose block:

compose.desktop.application {
    mainClass = "com.example.MainKt"
}

Or pass it via the command line:

./gradlew hotRun -PmainClass=com.example.MainKt

Packaging

Task Description
packageDistributionForCurrentOS Build all configured formats for the current OS
package<Format> Build a specific format (e.g., packageDmg, packageNsis, packageDeb)
packageReleaseDistributionForCurrentOS Same as above with ProGuard release build
createDistributable Create the application image without an installer
createReleaseDistributable Same with ProGuard

Utility

Task Description
suggestModules Suggest JDK modules required by your dependencies
packageUberJarForCurrentOS Create a single fat JAR with all dependencies

Running a Specific Task

# Build a DMG on macOS
./gradlew packageDmg

# Build NSIS installer on Windows
./gradlew packageNsis

# Build DEB package on Linux
./gradlew packageDeb

# Build all formats for current OS
./gradlew packageDistributionForCurrentOS

# Release build (with ProGuard)
./gradlew packageReleaseDistributionForCurrentOS

Output Location

Build artifacts are generated in:

build/compose/binaries/main/<format>/
build/compose/binaries/main-release/<format>/   # Release builds

Override with:

nativeDistributions {
    outputBaseDir.set(project.layout.buildDirectory.dir("custom-output"))
}

JDK Modules

The plugin does not automatically detect required JDK modules. Use suggestModules to identify them:

./gradlew suggestModules

Then declare them in the DSL:

nativeDistributions {
    modules("java.sql", "java.net.http", "jdk.accessibility")
}

Or include everything (larger binary):

nativeDistributions {
    includeAllModules = true
}

Application Icons

Provide platform-specific icon files:

nativeDistributions {
    macOS {
        iconFile.set(project.file("icons/app.icns"))
    }
    windows {
        iconFile.set(project.file("icons/app.ico"))
    }
    linux {
        iconFile.set(project.file("icons/app.png"))
    }
}
Platform Format Recommended Size
macOS .icns 1024x1024
Windows .ico 256x256
Linux .png 512x512

Application Resources

Include extra files in the installation directory via appResourcesRootDir:

nativeDistributions {
    appResourcesRootDir.set(project.layout.projectDirectory.dir("resources"))
}

Resource directory structure:

resources/
  common/          # Included on all platforms
  macos/           # macOS only
  macos-arm64/     # macOS Apple Silicon only
  macos-x64/       # macOS Intel only
  windows/         # Windows only
  linux/           # Linux only

Access at runtime:

val resourcesDir = File(System.getProperty("compose.application.resources.dir"))

Next Steps