The Kotlin framework
for cross-platform native desktop apps.

Real cross-platform — not just macOS, Windows and Linux, but the same Kotlin codebase as your Android, iOS and web apps. One language, every screen, every architecture.

Everywhere else, Kotlin owns the whole platform.
Now desktop does too.

On Android, Kotlin and Compose are first-class citizens. On iOS, Kotlin/Native reaches every UIKit and Foundation API while Compose renders like a true native app. On the web, Kotlin/JS and Wasm draw Compose UIs with the full browser API surface. Desktop had only half of that — you could render a window, but reaching the OS meant juggling pointers, compiling native libraries per platform, wiring JNI or FFM bridges, and learning a different native API for every OS — a wall most Kotlin developers couldn't climb. Nucleus closes the gap.

Android
OS APIsNative, built-in
Native UIMaterial 3 widgets
InputTouch · gestures
OptimizeR8 · ProGuard · AAB shrink
Package.aab via Gradle
DistributeGoogle Play, in two clicks
iOS
OS APIsKotlin/Native ↔ UIKit
Native UISwiftUI interop
InputTouch · Apple Pencil
OptimizeLLVM AOT · App Thinning
Package.ipa via Xcode
DistributeApp Store Connect
Web
Browser APIsKotlin/JS · Wasm
Native UIHTML / DOM interop
InputMouse · touch · pointer
OptimizeTree-shaking · code split
PackageWebpack bundle
DistributePush to any CDN
Desktop
OS APIsvia Nucleus30+ Kotlin modules · Native Access via Kotlin/Native
Native UIvia NucleusmacOS · Fluent · Yaru in Compose + native overlay
Inputvia NucleusMouse · keyboard · multi-touch · pen · Wayland gestures
Optimizevia NucleusGraalVM closed-world · JIT + AOT cache · native-lib stripping
Packagevia Nucleus16 formats, signed + notarized
Distributevia NucleusMS Store · App Store · Snap · GitHub · auto-update
Hybrid stack
JS / TS / DartIPCRust / C++ / Swift
Web UI in one language, native core in another, OS bindings per platform — every boundary becomes an IPC bridge, a serialization step, and a context switch in your head.
Nucleus + Compose
Kotlin
Compose for UI, Kotlin for logic, OS calls and packaging — one language top to bottom, no IPC, one mindset, one call graph.
Four native looks

Match every desktop, by design.

Write your UI once in Compose, render it in the desktop style of your choice — macOS, Windows 11 Fluent, Ubuntu Yaru, or IntelliJ Jewel. Each toolkit ships with a matching DecoratedWindow. macOS and Yaru are made by Nucleus; Jewel is JetBrains' official toolkit (the go-to for cross-platform IDE-like apps); Fluent comes from the open-source community.

Settings
General
Appearance
Network
Dark mode
macOS 26New · 2.0
Liquid Glass
macOS Tahoedecorated-window-macos26
Settings — Nucleus Demo
Appearance System
Dark mode
Follow system
Accent
FluentNew · 2.0
Mica · Acrylic
Windows 11decorated-window-fluent
Settings
Appearance
Dark style
Accent color
YaruNew · 2.0
GTK · LibAdwaita
Ubuntu · GNOMEdecorated-window-yaru
SettingsEditorPlugins
Appearance
Theme
Colors
Editor
Keymap
Theme
Darcula
Jewel
IntelliJ Platform
Cross-platform toolingdecorated-window-jewel
Two runtimes, one binary

Pick your tradeoff. Win either way.

Same Kotlin code, two runtimes: a GraalVM native image for instant cold start and a tiny resident set, or a modern JDK with AOT cache where HotSpot's JIT gets close to C++ and Rust on hot paths. Same source. Same build.

Closed world

GraalVM Native Image

Instant cold start. Tiny footprint.

Your whole app is AOT-compiled to a standalone binary. No JVM startup, no class loading — the process is alive in half a second. Smallest resident set on the market.

0.00s
Cold start
0MB
RAM idle
0MB
Binary
CPU throughputVery good · AOT compiled
C++
GraalVM PGO + Compose IR optimizations
Best for
CLIs & small appsSandboxed targetsApp Store / MSIXDistribution-first
nucleus.graalvm-runtime
Open world

JDK 25 + AOT Cache

Peak JIT throughput. Plugins, agents, full reflection.

HotSpot's C2 JIT is the most mature compiler ever built. JDK 25's AOT cache primes class metadata so you skip the warm-up — and you keep everything closed-world gives up: dynamic class loading, full reflection, JVM agents, scripting engines, live plugins and extensions.

0.0s
Cold start
0MB
RAM idle
0MB
Binary
CPU throughput≈ C++ / Rust on hot paths
C++
HotSpot C2 · escape analysis · vectorization
Best for
Plugin & extension hostsIDE-like toolsLong-running appsScripting & DSL runtimes
nucleus.aot-runtime
The Nucleus paradox

Native APIs.
Easier than native.

Win32 ITaskbarList3. NSUserNotifications. freedesktop D-Bus. IOKit. ScreenCaptureKit. Each desktop API is its own tiny ordeal — different language, different threading model, different conventions. Nucleus wraps every one in a Kotlin function that feels obvious. The result: a cross-platform abstraction simpler than the original, on every platform.

Native API · macOS · SwiftUI
1// SwiftUI app (2025) — still goes through UserNotifications + UNNotificationCenter
2import SwiftUI
3import UserNotifications
4
5@main
6struct MyApp: App {
7 @UIApplicationDelegateAdaptor(NotifDelegate.self) var delegate
8 var body: some Scene { WindowGroup { ContentView() } }
9}
10
11func postBuildNotif() async {
12 let center = UNUserNotificationCenter.current()
13
14 // 1. Authorization
15 let ok = try? await center.requestAuthorization(options: [.alert, .sound])
16 guard ok == true else { return }
17
18 // 2. Declare the actions and register the category up-front
19 let reveal = UNNotificationAction(identifier: "REVEAL",
20 title: "Reveal in Finder", options: [.foreground])
21 let copy = UNNotificationAction(identifier: "COPY",
22 title: "Copy path", options: [])
23 let share = UNNotificationAction(identifier: "SHARE",
24 title: "Share…", options: [.foreground])
25
26 let cat = UNNotificationCategory(identifier: "BUILD_DONE",
27 actions: [reveal, copy, share], intentIdentifiers: [],
28 options: .customDismissAction)
29 center.setNotificationCategories([cat])
30
31 // 3. Build content
32 let content = UNMutableNotificationContent()
33 content.title = "Build complete"
34 content.body = "Installer ready. What now?"
35 content.categoryIdentifier = "BUILD_DONE"
36 content.sound = .default
37
38 let req = UNNotificationRequest(identifier: UUID().uuidString,
39 content: content, trigger: nil)
40 try? await center.add(req)
41}
42
43// 4. Delegate to receive callbacks (must be retained, AppDelegate is easiest)
44class NotifDelegate: NSObject, UIApplicationDelegate,
45 UNUserNotificationCenterDelegate {
46 func application(_ a: UIApplication, didFinishLaunchingWithOptions o:
47 [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
48 UNUserNotificationCenter.current().delegate = self
49 return true
50 }
51
52 func userNotificationCenter(_ c: UNUserNotificationCenter,
53 didReceive r: UNNotificationResponse,
54 withCompletionHandler done: @escaping () -> Void) {
55 switch r.actionIdentifier {
56 case "REVEAL": revealInFinder(file)
57 case "COPY": copyPath(file)
58 case "SHARE": shareSheet(file)
59 case UNNotificationDismissActionIdentifier:
60 telemetry.log("notif_dismissed")
61 default: break
62 }
63 done()
64 }
65}
66// + Info.plist NSUserNotificationsUsageDescription
67// + handle authorization revoked mid-app-lifecycle
~74 linesThreading model: yours to figure out
One Kotlin API · all platforms
1import dev.nucleusframework.notification.notify
2import dev.nucleusframework.notification.NotificationAction
3
4notify(
5 title = "Build complete",
6 body = "Installer ready. What now?",
7 icon = Icon.AppIcon,
8 actions = listOf(
9 NotificationAction("reveal", "Reveal in Finder") {
10 Desktop.open(file.parent)
11 },
12 NotificationAction("copy", "Copy path") {
13 Clipboard.put(file.absolutePath)
14 },
15 NotificationAction("share", "Share…") { shareSheet(file) },
16 ),
17 onDismiss = { telemetry.log("notif_dismissed") },
18)
18 linesCoroutines-friendly · type-safe · zero callbacks lost
From tag to release

Push a tag. Get signed installers.

Nucleus ships reusable GitHub Actions that build, sign, notarize, bundle and publish for every desktop — without a copy-pasted YAML in sight. Six composite actions, one reference workflow, one tag push.

Trigger
git push tag v1.0.0
Matrix build
6 parallel runners
Ubuntu · amd64Ubuntu · arm64Windows · amd64Windows · arm64macOS · arm64macOS · x64
Sign · bundle · notarize
lipo universal · MSIX · staple
GitHub Release
installers + auto-update YAML
Six composite actions
setup-nucleus

JBR 25 or Liberica NIK, Gradle cache, Node, Linux packaging tools — one step, every runner.

setup-macos-signing

Temporary keychain, .p12 imported from secrets, identities exposed to downstream steps.

build-macos-universal

lipo merge arm64 + x64, inside-out re-sign, notarize via notarytool, staple — one DMG out.

build-windows-appxbundle

Merge amd64 + arm64 .appx into a .msixbundle, sign with SignTool — Microsoft Store ready.

generate-update-yml

SHA-512 every installer, emit latest-mac.yml / latest.yml / latest-linux.yml for the auto-updater.

publish-release

gh release create with the right assets, marks -alpha / -beta / -rc as pre-release automatically.