Compose Desktop, prêt pour la prod

Shippe le desktop avec l'équipe Kotlin que tu as déjà.

Compose Multiplatform dessine l'UI. Nucleus en fait une vraie app desktop — chrome natif, APIs OS, packaging et stores. La même base Kotlin que tes apps Android, iOS et web. Pas de seconde stack. Pas de JNI circus.

Partout ailleurs, Kotlin règne sur toute la plateforme.
Le desktop aussi, maintenant.

Sur Android, Kotlin et Compose sont citoyens de première classe. Sur iOS et le web, même histoire. Le desktop avait Compose pour l'UI — et te laissait inventer le reste : chrome natif, APIs OS, signature, auto-update, stores. Compose Desktop vanilla s'arrête à la fenêtre. Nucleus est la couche de production qui manquait à ton équipe Kotlin.

Android
APIs OSNatives, intégrées
UI nativeWidgets Material 3
EntréesTactile · gestes
OptimisationR8 · ProGuard · réduction AAB
Empaquetage.aab via Gradle
DistributionGoogle Play, en deux clics
iOS
APIs OSKotlin/Native ↔ UIKit
UI nativeInterop SwiftUI
EntréesTactile · Apple Pencil
OptimisationLLVM AOT · App Thinning
Empaquetage.ipa via Xcode
DistributionApp Store Connect
Web
APIs navigateurKotlin/JS · Wasm
UI nativeInterop HTML / DOM
EntréesSouris · tactile · pointeur
OptimisationTree-shaking · code splitting
EmpaquetageBundle Webpack
DistributionPush sur n'importe quel CDN
Desktop
APIs OSvia Nucleus40+ modules Kotlin · accès natif via Kotlin/Native
UI nativevia NucleusmacOS · Fluent · Yaru en Compose + overlay natif
Entréesvia NucleusSouris · clavier · multi-touch · stylet · gestes Wayland
Optimisationvia NucleusGraalVM closed-world · cache JIT + AOT · stripping des libs natives
Empaquetagevia Nucleus18 formats, signés + notarisés
Distributionvia NucleusMS Store · App Store · Snap · GitHub · mise à jour auto
Compose Desktop vanilla
Pas de tactile / styletTray obsolèteInutilisable en prod
Fenêtre Skia, souris et clavier uniquement — pas de multi-touch, pas de stylet. Le tray Windows et Linux est obsolète et à peine utilisable ; les notifications restent basiques. L'intégration système est une couche de démo, pas un stack desktop de production. Six formats jpackage ; chrome, signature, auto-update et stores restent à votre charge.
Compose + Nucleus
Chrome natif40+ modules OSShip & stores
La même UI Compose — plus fenêtres décorées natives, 40+ modules OS Kotlin, 18 formats de packaging, auto-update et CI prête pour les stores. Drop-in sur le plugin JetBrains.
Piles incluses

Il livre aussi des composants — une seule API Compose, chaque plateforme.

Chacun remplace quatre moteurs natifs qu'il faudrait sinon écrire, tester et garder synchronisés — derrière un seul composable identique sur Android, iOS, web et desktop.

Lecteur PDF
PdfReader(state)dev.nucleusframework:pdfium
remplacePdfRendererPDFKitPDF.jsPDFBox
WebView
WebView(state)dev.nucleusframework:composewebview
remplaceWebViewWKWebViewiframeWebView2
Runtime

40+ modules.
Chaque fonctionnalité OS, citoyenne de première classe.

TextureView et NativeView placent textures GPU et widgets natifs dans Compose. L'auto-update différentiel ne télécharge que les blocs modifiés. Le Task Scheduler lance du travail en arrière-plan comme WorkManager, même app fermée. Et toute la surface OS — notifications, tray, raccourcis globaux, mode sombre — une API Kotlin par capacité.

Nouveau dans 2.4
Contexte de rendu GPU
GPU in-process sur le device de la scène — DirectContext Skia, Metal / ANGLE / EGL. Pas de second GPU, pas de copie.
Nouveau dans 2.4
TextureView
Textures GPU externes dans la scène Compose — D3D11, Metal, DMA-BUF. Vrai ordre z, sans copie CPU.
Nouveau dans 2.4
AwakeMode
Gardez le système éveillé pour les jobs longs sans forcer l'écran — SYSTEM_ONLY vs SYSTEM_AND_DISPLAY.
NativeView
Intégrez un NSView, un HWND ou un GtkWidget dans Compose — dimensionné au slot de layout, libéré avec la composition.
Mises à jour différentielles
Ne téléchargez que les blocs modifiés — block maps electron-builder, requêtes HTTP range, repli silencieux sur le téléchargement complet.
Task Scheduler
Le WorkManager du desktop — tâches périodiques, cron et au boot que l'OS lance même app fermée. launchd, Task Scheduler, systemd.
Fenêtre décorée
Barre de titre personnalisée, contrôles natifs, adaptée au thème. Backend Tao par défaut.
Scaffold de fenêtre
Mises en page plein fenêtre, régions de verre, Mica/Acrylic, primitives de chrome.
Notifications natives
macOS, Toast Windows, freedesktop — une seule API Kotlin, plus options DSL par plateforme.
Zone de notification
Icônes de statut avec menus, badges et clics — sur les trois systèmes.
Dock et launcher
Badges, jump lists, menus du dock, entrées du launcher Unity.
Détecteur de mode sombre
Thème système réactif — relie isSystemInDarkTheme de Compose sous nucleusApplication.
Raccourci global
Raccourcis au niveau OS, multi-modificateurs, valables dans toute l'app — ids portail stables sous Wayland.
Progression barre des tâches
Barres de progression sur la barre des tâches Windows, le dock macOS et le launcher Unity.
Liens profonds
Gestionnaires de protocole et associations de fichiers sur toutes les plateformes.
HTTP / SSL natifs
Magasin de confiance de l'OS fusionné aux valeurs par défaut du JDK.
Native Access
Écrivez en Kotlin/Native et appelez depuis la JVM. Sans C, sans glue.
Propulsé par TaoBackend par défaut

Tao est la crate de fenêtrage Rust derrière Tauri 2. Nucleus en fait le backend de fenêtre par défaut — sans AWT — : TextureView pour les textures GPU externes, NativeView pour les widgets natifs, Wayland natif, multi-touch, stylet et chrome via window scaffold, dans le même arbre Compose.

TextureView
Textures GPU externes compositées dans la scène — D3D11, Metal, DMA-BUF. Aucune copie CPU des frames.
NativeView
Embarquez un NSView, HWND ou GtkWidget dans le layout Compose — même cycle de vie de slot qu'AndroidView.
Wayland natif
Support Wayland de premier plan — sans repli XWayland, scaling fractionnaire, gestes.
Multi-touch et stylet
Pinch, swipe, rotation, pression et inclinaison — chaque événement pointeur porte la source complète.
Accessibilité native

Un arbre de sémantique. Trois lecteurs d'écran natifs.

Le backend Tao projette ta sémantique Compose sur NSAccessibility, UI Automation et AT-SPI. VoiceOver, Narrator et Orca fonctionnent directement — pas de câblage supplémentaire, pas de code spécifique par plateforme. Et l'accessibilité compte plus que jamais : alors que les agents IA interagissent de plus en plus avec les applications, ils s'appuient sur les mêmes arbres d'accessibilité structurés pour lire et contrôler les programmes.

Paramètres
CompteActif
VoiceOver
Le focus se déplace sur le switch
macOSAXIdentifier · testTag
VoiceOver·NSAccessibility
Accès facile
Narrateur
Décrire le monde autour de moi
Élément focalisé
WindowsAutomationId · testTag
Narrator·UI Automation
Accessibilité
Lecteur d'écran
OLecteur d'écran Orca
Bus AT-SPI ponté via AccessKit
LinuxAccessKit author id · testTag
Orca·AT-SPI via AccessKit
Aucune technologie d'assistance connectée ? Le backend saute le parcours entièrement pour garder le défilement et les animations fluides. La première requête d'un lecteur d'écran active la projection automatiquement.
Cinq looks natifs

Colle à chaque desktop, par design.

Une UI écrite une fois en Compose, rendue dans le style desktop voulu — macOS 26 Liquid Glass, Windows 11 Fluent, Ubuntu Yaru, IntelliJ Jewel ou Material 3 multiplateforme. macOS, Fluent et Yaru sont des design systems open-source sur Maven Central (avec fenêtres décorées basées sur Nucleus) ; Jewel est le toolkit JetBrains ; Material 3 est le repli Nucleus.

Paramètres
Général
Apparence
Réseau
Mode sombre
Liquid Glass
macOS Tahoecompose-macos-ui
Paramètres — Démo Nucleus
Apparence Système
Mode sombre
Suivre le système
Accent
Mica · Acrylic
Windows 11composefluent
Paramètres
Apparence
Style sombre
Couleur d'accent
GTK · LibAdwaita
Ubuntu · GNOMEyarucompose
ParamètresÉditeurPlugins
Apparence
Thème
Couleurs
Éditeur
Raccourcis
Thème
Darcula
Jewel
IntelliJ Platform
Outils multiplateformesdecorated-window-jewel
Paramètres
Mode sombre
Suivre le système
Couleur dynamiqueAccent
Material 3
Material You
Multiplateformedecorated-window-material3

Choisissez un toolkit par OS, ou mélangez librement — chaque design system tourne sur chaque plateforme. Vous pouvez livrer un build Fluent sur macOS le temps de prototyper le look natif. Dans tous les cas, le DecoratedWindow reste le même Composable.

Deux runtimes, un seul binaire

Choisis ton compromis. Tu gagnes dans les deux cas.

Le même code Kotlin, deux runtimes : une image native GraalVM pour un démarrage à froid instantané et une empreinte minuscule, ou un JDK moderne avec cache AOT où le JIT de HotSpot s'approche du C++ et de Rust sur les chemins chauds. Même source. Même build.

Closed world

GraalVM Native Image

Démarrage à froid instantané. Empreinte minuscule.

L'app entière est compilée AOT en binaire autonome. Pas de démarrage JVM, pas de chargement de classes — le process est vivant en une demi-seconde. La plus petite empreinte mémoire du marché.

0.0s
Démarrage à froid
0MB
RAM au repos
0MB
Binaire
Débit CPUTrès bon · compilé AOT
C++
PGO GraalVM + optimisations IR Compose
Idéal pour
CLIs & petites appsCibles sandboxéesApp Store / MSIXDistribution avant tout
nucleus.graalvm-runtime
Open world

JDK 25 + cache AOT

Débit JIT au sommet. Plugins, agents, réflexion totale.

Le JIT C2 de HotSpot est le compilateur le plus mûr jamais construit. Le cache AOT de JDK 25 amorce les métadonnées de classes : le warm-up disparaît — et tout ce que le closed-world abandonne reste accessible : chargement dynamique, réflexion totale, agents JVM, moteurs de scripting, plugins et extensions à chaud.

0.0s
Démarrage à froid
0MB
RAM au repos
0MB
Binaire
Débit CPU≈ C++ / Rust sur les chemins chauds
C++
HotSpot C2 · escape analysis · vectorisation
Idéal pour
Hôtes de plugins / extensionsOutils de type IDEApps long-runningRuntimes scripting / DSL
nucleus.aot-runtime

* Démarrage à froid et RAM mesurés sur Windows 11 avec un build Hello World. La taille du binaire correspond à l’installateur NSIS avec compression maximale.

Le paradoxe Nucleus

APIs natives.
Plus simple que le natif.

Win32 ITaskbarList3. NSUserNotifications. freedesktop D-Bus. IOKit. ScreenCaptureKit. Chaque API desktop est son propre petit calvaire — langage différent, modèle de threading différent, conventions différentes. Nucleus enveloppe chacune dans une fonction Kotlin qui paraît évidente. Résultat : une abstraction multiplateforme plus simple que l'originale, sur chaque plateforme.

API native · 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 linesModèle de threading : à la charge du développeur
Une seule API Kotlin · toutes plateformes
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 lignesCompatible coroutines · type-safe · zéro callback perdu
Du tag à la release

Pousse un tag. Récupère des installeurs signés.

Nucleus livre des GitHub Actions réutilisables qui compilent, signent, notarisent, empaquettent et publient pour chaque desktop — sans YAML copié-collé. Six actions composites, un workflow de référence, un seul push de tag.

Déclenchement
git push tag v1.0.0
Build matriciel
6 runners en parallèle
Ubuntu · amd64Ubuntu · arm64Windows · amd64Windows · arm64macOS · arm64macOS · x64
Signer · bundler · notariser
lipo universal · MSIX · staple
GitHub Release
installeurs + block maps + YAML update
Six actions composites
setup-nucleus

JBR 25 ou Liberica NIK, cache Gradle, Node, outils de packaging Linux — une étape, tout runner.

setup-macos-signing

Trousseau temporaire, .p12 importé depuis les secrets, identités exposées aux étapes suivantes.

build-macos-universal

Fusion lipo arm64 + x64, re-sign inside-out, notarisation via notarytool, staple — un DMG en sortie.

build-windows-appxbundle

Fusion amd64 + arm64 .appx en .msixbundle, signature SignTool — prêt pour le Microsoft Store.

generate-update-yml

SHA-512 de chaque installeur, génère latest-*.yml et les block maps electron-builder pour ne télécharger que les blocs modifiés.

publish-release

gh release create avec les bons assets, marque -alpha / -beta / -rc en pre-release automatiquement.

Discutez avec nous

Une question, une migration coincée, ou juste pour lire. #nucleus est sur le Slack officiel Kotlin.