Files
keluna/docs/keluna-concept.md
2026-09-16 11:03:07 +02:00

997 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Keluna
**Kotlin Embedded Local UI for Native Applications**
Keluna ist die Idee für ein leichtgewichtiges Framework zur Entwicklung nativer Desktop-Anwendungen für Linux, macOS und Windows mit **Kotlin/Native**.
Das Ziel ist eine Entwicklererfahrung ähnlich moderner Kotlin-UI-Frameworks, ohne dafür eine JVM, eine eigene Rendering-Engine oder einen mitgelieferten Browser zu benötigen.
Keluna kombiniert dafür drei grundlegende Konzepte:
- **Kotlin/Native** für Anwendungscode und Betriebssystemintegration
- ein **Vaadin-Flow-artiges Komponentenmodell** für die Beschreibung und Verwaltung der UI
- die vorhandene **System-WebView** des jeweiligen Betriebssystems als Rendering-Engine
Dadurch sollen kleine, schnell startende Desktop-Anwendungen entstehen, deren Anwendungscode nahezu vollständig in Kotlin geschrieben werden kann.
---
## Motivation
Für plattformübergreifende Desktop-Anwendungen existieren heute mehrere etablierte Ansätze.
### Electron
Electron bietet eine sehr komfortable Web-Entwicklungsumgebung, liefert jedoch Chromium und Node.js mit jeder Anwendung aus.
Selbst kleine Anwendungen erreichen dadurch schnell Größen von deutlich über 100 MB und benötigen vergleichsweise viel Arbeitsspeicher.
### Compose Multiplatform
Compose Multiplatform ermöglicht eine hervorragende Kotlin-Entwicklung, basiert auf dem Desktop jedoch auf der JVM und einer eigenen Rendering-Infrastruktur.
Dadurch entstehen ebenfalls relativ große Distributionen und zusätzliche Startkosten durch JVM und UI-Runtime.
### Tauri
Tauri vermeidet den eingebetteten Browser und verwendet stattdessen die WebView des Betriebssystems.
Dadurch können Anwendungen sehr klein bleiben.
Die typische Architektur besteht jedoch aus zwei Welten:
- TypeScript oder JavaScript für das Frontend
- Rust für den nativen Teil
### Qt
Qt ermöglicht kleine und schnelle Desktop-Anwendungen, verwendet traditionell jedoch C++.
Rust-Bindings verbessern diese Situation, dennoch bleibt Qt ein großes, eigenständiges UI-Ökosystem.
---
## Grundidee
Keluna soll einen anderen Weg gehen:
> Die Anwendung ist eine Kotlin/Native-Anwendung.
> Die System-WebView ist lediglich ihre Rendering-Engine.
Die Anwendung selbst lebt vollständig im nativen Kotlin-Prozess.
```text
┌──────────────────────────────────────────────┐
│ Kotlin/Native App │
│ │
│ Domain Model │
│ Application State │
│ Services │
│ UI Component Tree │
│ Event Handler │
│ OS Integration │
└─────────────────────┬────────────────────────┘
│
UI Synchronisation
│
kleines IPC-Protokoll
│
┌─────────────────────▼────────────────────────┐
│ JavaScript Runtime │
│ │
│ DOM Updates │
│ Event Forwarding │
│ Browser Interaction │
└─────────────────────┬────────────────────────┘
│
DOM
│
┌─────────────────────▼────────────────────────┐
│ System WebView │
│ │
│ Windows WebView2 │
│ macOS WKWebView │
│ Linux WebKitGTK │
└──────────────────────────────────────────────┘
```
Keluna bringt damit **keine eigene Browser-Engine** mit.
Ebenso benötigt Keluna:
- keine JVM
- kein Chromium-Bundle
- kein Node.js
- keine eigene GPU-Rendering-Engine
---
## Inspirationsquellen
Keluna kombiniert Ideen aus mehreren existierenden Frameworks, ohne eines davon direkt nachzubauen.
### Kotlin und Compose
Von Kotlin und Compose übernimmt Keluna vor allem die gewünschte Entwicklerergonomie:
- typsichere APIs
- Kotlin DSLs
- Properties und State
- deklarative UI-Beschreibung
- gute Integration mit Coroutines
- Gradle als Build-System
Ein Keluna-Programm könnte beispielsweise konzeptionell so aussehen:
```kotlin
window("Keluna Demo") {
verticalLayout {
textField("Repository")
button("Open") {
openRepository()
}
}
}
```
Die genaue API ist dabei noch offen.
Wichtig ist das Prinzip:
**Der Anwendungsentwickler soll möglichst ausschließlich Kotlin sehen.**
### Vaadin Flow
Von Vaadin Flow übernimmt Keluna die Idee eines **serverseitigen Komponentenbaums**.
Bei Vaadin existieren Komponenten als Java-Objekte auf dem Server. Änderungen an diesen Objekten werden mit dem DOM im Browser synchronisiert.
Keluna verwendet ein ähnliches Modell, jedoch ohne Netzwerk.
Bei einer Desktop-Anwendung befinden sich beide Seiten lokal:
```text
Vaadin Flow
Java Server
│
│ HTTP / WebSocket
▼
Browser
```
Keluna reduziert dieses Modell auf:
```text
Kotlin/Native
│
│ lokale WebView Bridge
▼
System WebView
```
Dadurch entfallen große Teile der Komplexität von Vaadin:
- HTTP
- WebSocket
- Sessions
- Reconnect
- Authentication zwischen Client und Server
- Netzwerk-Retry
- Cluster-Synchronisation
Übrig bleibt im Wesentlichen:
```text
Component Tree
│
▼
DOM Patch
│
▼
WebView
WebView
│
▼
Event
│
▼
Kotlin Handler
```
### Tauri
Von Tauri übernimmt Keluna vor allem das Prinzip:
> Nutze die Browser-Engine, die das Betriebssystem ohnehin bereitstellt.
Keluna verwendet deshalb unterschiedliche WebView-Implementierungen:
| Plattform | WebView |
|---|---|
| Windows | WebView2 |
| macOS | WKWebView |
| Linux | WebKitGTK |
Die WebView ist dabei kein eigenständiger Anwendungsteil.
Sie ist lediglich der Renderer für:
- HTML
- CSS
- Text
- Layout
- Form Controls
- SVG
- Animationen
---
## Architektur
Keluna könnte zunächst aus sechs grundlegenden Bereichen bestehen.
```text
keluna-core
keluna-ui
keluna-runtime
keluna-web
keluna-platform
keluna-components
```
### `keluna-core`
Enthält grundlegende Framework-Abstraktionen.
Beispielsweise:
```text
Component
Element
Property
State
Event
StateTree
```
Dieses Modul sollte weitgehend unabhängig von den konkreten Plattformen sein.
### `keluna-ui`
Enthält die Kotlin-API zur Beschreibung der Benutzeroberfläche.
Beispielsweise:
```text
Window
Layout
Button
TextField
Checkbox
Select
Table
Dialog
Tabs
Menu
```
Darauf baut die Kotlin-DSL auf.
### `keluna-runtime`
Verwaltet den Komponentenbaum und den Anwendungszustand.
Aufgaben sind unter anderem:
- Component Lifecycle
- State Management
- Event Dispatching
- Erkennung von Änderungen
- Erzeugung von DOM-Patches
- Synchronisation mit der WebView
### `keluna-web`
Enthält die kleine JavaScript-Runtime innerhalb der WebView.
Diese Runtime sollte bewusst minimal bleiben.
Ihre Aufgaben:
- DOM-Elemente erzeugen
- DOM-Properties ändern
- Elemente entfernen
- Events registrieren
- relevante Browser-Events an Kotlin weiterleiten
Beispielsweise könnte Kotlin intern folgende Instruktion erzeugen:
```json
{
"op": "set",
"node": 17,
"property": "textContent",
"value": "Open"
}
```
Oder:
```json
{
"op": "append",
"parent": 3,
"node": 17
}
```
Ein Klick könnte in Gegenrichtung übertragen werden:
```json
{
"node": 17,
"event": "click"
}
```
Das Protokoll sollte später vermutlich kompakter sein als JSON.
Für einen ersten Prototyp wäre JSON jedoch ideal.
---
## Plattform-Layer
Keluna benötigt für jedes Betriebssystem einen sehr kleinen nativen Adapter.
```text
keluna-platform
│
├── linux
│ ├── GTK
│ └── WebKitGTK
│
├── macos
│ ├── Cocoa
│ └── WKWebView
│
└── windows
├── Win32
└── WebView2
```
Die gemeinsame API könnte beispielsweise Funktionen bereitstellen wie:
```text
createWindow()
loadResource()
evaluateJavaScript()
receiveMessage()
showFileDialog()
setClipboard()
showNotification()
```
Die Anwendung selbst soll diese Plattformunterschiede normalerweise nicht sehen.
---
## Native Desktop-Funktionen
Keluna soll nicht nur eine Web-Anwendung in einem Fenster darstellen.
Der Kotlin-Prozess besitzt direkten Zugriff auf das Betriebssystem.
Dadurch können Anwendungen beispielsweise folgende Funktionen nutzen:
- Dateisystemzugriff
- native File Dialogs
- Clipboard
- Drag & Drop
- Notifications
- System Tray
- Menüleiste
- Prozesse starten
- lokale Sockets
- Git
- Credential Stores
- Betriebssysteminformationen
Diese Funktionen können als Kotlin-APIs bereitgestellt werden.
```text
Keluna Application
│
├── UI
│
├── Files
├── Process
├── Clipboard
├── Notifications
├── Dialogs
└── Platform APIs
```
---
## Verantwortlichkeit zwischen Kotlin und WebView
Nicht jede UI-Interaktion sollte den Kotlin-Prozess erreichen.
Lokale Browserfunktionen sollten möglichst lokal bleiben.
### WebView
Die WebView übernimmt beispielsweise:
- Hover
- CSS
- Animationen
- Scrolling
- Text Selection
- Focus-Darstellung
- Cursor
- einfache visuelle Interaktionen
### Kotlin
Kotlin übernimmt:
- Application State
- Navigation
- Business Logic
- Commands
- persistente UI-Zustände
- Dateisystem
- Prozesse
- Netzwerk
- Git
- Betriebssystemintegration
Dadurch bleibt die IPC-Schicht klein.
---
## State und Synchronisation
Der zentrale Bestandteil von Keluna wäre ein State Tree ähnlich dem Komponentenmodell von Vaadin Flow.
Beispiel:
```text
Window #1
└── VerticalLayout #2
├── TextField #3
├── Button #4
└── Label #5
```
Jede Komponente besitzt eine interne ID.
Ändert Kotlin beispielsweise:
```text
Label #5
"Ready"
↓
"Loading..."
```
muss lediglich folgende Änderung an die WebView übertragen werden:
```text
SET #5 textContent "Loading..."
```
Es wird nicht die gesamte Benutzeroberfläche neu aufgebaut.
---
## Event-Modell
Events laufen in Gegenrichtung.
Beispielsweise:
```text
WebView
Button #4 clicked
│
▼
IPC
│
▼
Keluna Runtime
│
▼
Kotlin callback
```
In der Anwendung könnte das beispielsweise so aussehen:
```kotlin
button("Open") {
openProject()
}
```
Keluna registriert intern lediglich:
```text
#4 → click → callback
```
---
## HTML und CSS
HTML und CSS sind Implementierungsdetails der Rendering-Schicht.
Der Entwickler muss sie nicht zwingend direkt verwenden.
Für fortgeschrittene Anwendungen sollte Keluna sie jedoch nicht verstecken.
Denkbar wären deshalb mehrere Ebenen:
```text
High Level
Keluna Components
↓
Keluna Element API
↓
HTML / CSS
↓
System WebView
```
Dadurch könnten Entwickler bei Bedarf eigene Web Components oder CSS einbinden.
---
## Custom Components
Neben Standardkomponenten sollte Keluna eigene Komponenten erlauben.
Beispielsweise:
```text
Graph
CodeEditor
Tree
MarkdownViewer
Terminal
Diagram
```
Solche Komponenten könnten aus:
- Kotlin
- HTML
- CSS
- etwas JavaScript
bestehen.
Für Spezialfälle könnte auch eine bestehende JavaScript-Komponente eingebettet werden.
Keluna soll JavaScript also nicht verbieten.
Es soll lediglich **für normale Anwendungsentwicklung nicht notwendig sein**.
---
## Packaging
Ein wichtiges Ziel von Keluna ist eine kleine Distribution.
Eine Anwendung besteht im Wesentlichen aus:
```text
Kotlin/Native executable
+
Keluna runtime
+
HTML/CSS/JS resources
```
Die Browser-Engine wird nicht mitgeliefert.
Auf den Plattformen wird stattdessen verwendet:
```text
Windows → WebView2
macOS → WKWebView
Linux → WebKitGTK
```
Unter Linux würden GTK und WebKitGTK typischerweise Paketabhängigkeiten darstellen.
Ein Debian-Paket könnte beispielsweise von diesen Systembibliotheken abhängen, anstatt sie selbst mitzubringen.
Dadurch sollte eine einfache Keluna-Anwendung potenziell im Bereich von **wenigen Megabyte bis niedrigen zweistelligen Megabyte** bleiben können.
Die tatsächliche Größe müsste durch einen Prototyp überprüft werden.
---
## Startzeit
Keluna benötigt:
- keine JVM-Initialisierung
- keinen Node-Prozess
- keinen Start eines eingebetteten Chromium
- keine eigene Grafik-Runtime
Der native Prozess startet lediglich die vorhandene WebView und lädt lokale Ressourcen.
Damit sollte die Startzeit eher in der Größenordnung kleiner nativer Anwendungen bzw. Tauri-Anwendungen liegen als bei Compose Desktop oder Electron.
Auch dies müsste frühzeitig durch einen Proof of Concept gemessen werden.
---
## Ziele
Keluna soll:
- Desktop-Anwendungen vollständig oder nahezu vollständig in Kotlin ermöglichen
- Kotlin/Native verwenden
- Linux, macOS und Windows unterstützen
- kleine Distributionen erzeugen
- schnell starten
- die vorhandene System-WebView verwenden
- keine eigene Rendering-Engine benötigen
- keinen Webserver starten
- keine JVM voraussetzen
- keine JavaScript-Anwendungsarchitektur erzwingen
- sich natürlich in Gradle und Kotlin Multiplatform integrieren
---
## Nicht-Ziele
Keluna soll zunächst ausdrücklich **kein**:
- Browser-Webframework
- Mobile-Framework
- eigener Browser
- eigener HTML-Renderer
- eigener GPU-Renderer
- Electron-Ersatz mit eingebettetem Chromium
- vollständiges Vaadin-Flow-Reimplementation
sein.
Ebenso sollte Keluna nicht versuchen, von Anfang an hunderte UI-Komponenten bereitzustellen.
---
## Ein mögliches MVP
Ein erster Proof of Concept benötigt überraschend wenig.
### Phase 1 – WebView
Für eine Plattform, beispielsweise Linux:
- Kotlin/Native Executable
- GTK-Fenster
- WebKitGTK-WebView
- lokale `index.html` laden
- JavaScript aus Kotlin aufrufen
- Nachricht von JavaScript an Kotlin senden
Damit wäre die technische Grundlage bewiesen.
### Phase 2 – Element Tree
Ein einfacher Kotlin-Elementbaum:
```text
Window
Column
Text
Button
```
Dieser erzeugt DOM-Strukturen.
### Phase 3 – Events
Browser-Events werden an Kotlin übertragen:
```text
click
change
input
keydown
```
### Phase 4 – State Synchronisation
Änderungen im Kotlin-Component-Tree erzeugen nur noch inkrementelle DOM-Patches.
### Phase 5 – weitere Plattformen
Implementierung von:
- WKWebView für macOS
- WebView2 für Windows
### Phase 6 – Desktop APIs
Erste native Funktionen:
- File Picker
- Clipboard
- Notifications
- Prozessstart
---
## Mögliche Modulstruktur
```text
keluna/
├── keluna-core
├── keluna-ui
├── keluna-runtime
├── keluna-components
├── keluna-web-runtime
├── keluna-platform-linux
├── keluna-platform-macos
├── keluna-platform-windows
└── keluna-gradle-plugin
```
Eine Anwendung könnte anschließend beispielsweise nur benötigen:
```text
keluna-core
keluna-components
keluna-platform
```
---
## Gradle-Integration
Langfristig sollte eine Keluna-Anwendung über ein Gradle-Plugin konfiguriert werden können.
Konzeptionell:
```kotlin
plugins {
kotlin("multiplatform")
id("dev.keluna.application")
}
keluna {
applicationName = "My Application"
mainClass = "MainKt"
}
```
Das Plugin könnte anschließend:
- Kotlin/Native Targets konfigurieren
- Web-Ressourcen bündeln
- native Abhängigkeiten konfigurieren
- Installer erzeugen
- Signing vorbereiten
- Plattformpakete bauen
---
## Entwicklungsmodell
Keluna könnte zwei Ebenen anbieten.
### High-Level
Für normale Anwendungen:
```text
Keluna Components
+
Kotlin State
+
Kotlin Event Handler
```
Der Entwickler benötigt keine Webkenntnisse.
### Low-Level
Für Spezialkomponenten:
```text
DOM
CSS
JavaScript
Web Components
```
Dadurch bleibt das Framework offen.
Eine komplexe Komponente wie ein Code-Editor könnte beispielsweise intern Monaco oder CodeMirror verwenden, während die restliche Anwendung vollständig in Kotlin bleibt.
---
## Designprinzipien
### Kotlin first
Die öffentliche API wird für Kotlin entworfen und nicht aus einer anderen Sprache übernommen.
### Native application first
Keluna ist kein Webframework, das zufällig Desktop-Fenster erzeugt.
Es ist ein Desktop-Framework, das Web-Technologie zum Rendern verwendet.
### System WebView instead of bundled browser
Der größte Baustein vieler Desktop-Webframeworks wird bewusst nicht ausgeliefert.
### Thin client
Die JavaScript-Runtime sollte möglichst klein und weitgehend zustandslos bleiben.
### Escape hatches
HTML, CSS und JavaScript bleiben erreichbar, wenn eine Anwendung sie benötigt.
### Incremental adoption
Eine Anwendung sollte mit wenigen Standardkomponenten beginnen können und später komplexere eigene Komponenten hinzufügen können.
### Measure early
Binary-Größe, RAM-Verbrauch und Startzeit sind zentrale Eigenschaften des Projekts und sollten von Anfang an automatisiert gemessen werden.
---
## Risiken
### Unterschiedliche WebView-Engines
Windows verwendet Chromium über WebView2.
macOS und Linux verwenden WebKit.
Dadurch können Unterschiede bei:
- CSS
- JavaScript
- Web APIs
- Rendering
auftreten.
Keluna sollte deshalb bewusst nur auf gut unterstützte Webstandards setzen.
### Linux-Abhängigkeiten
Linux besitzt keine so klar definierte System-WebView wie macOS.
WebKitGTK und GTK müssen auf dem Zielsystem vorhanden sein.
Distribution und Packaging müssen deshalb früh untersucht werden.
### Kotlin/Native Interop
Die Plattformadapter benötigen Interop mit:
- Win32 und COM
- Cocoa/Objective-C
- GTK und WebKitGTK
Dieser Bereich dürfte einer der technisch anspruchsvollsten Teile des Frameworks sein.
Er bleibt jedoch innerhalb des Frameworks verborgen und betrifft nicht den normalen Anwendungsentwickler.
### UI-State-Komplexität
Ein nativer Komponentenbaum klingt zunächst einfach.
Komplexität entsteht jedoch bei:
- Textfeldern während der Eingabe
- Selection
- Focus
- Cursorpositionen
- Drag & Drop
- großen Tabellen
- virtuellen Listen
Keluna sollte deshalb nicht versuchen, jeden Browserzustand permanent nach Kotlin zu spiegeln.
---
## Langfristige Perspektive
Keluna könnte langfristig drei Ebenen bilden:
```text
Keluna
│
┌───────────┴───────────┐
│ │
Kotlin Components Custom Components
│ │
└───────────┬───────────┘
│
Component Tree
│
Keluna Runtime
│
WebView
│
Native Platform
```
Damit entsteht ein ungewöhnliches Desktop-Modell:
> **Native application logic with web-based rendering, without turning the application itself into a web application.**
---
## Zusammenfassung
Keluna kombiniert drei bewährte Ideen:
### Kotlin/Native
für:
- Anwendungscode
- Domain-Logik
- State
- Betriebssystemzugriffe
### Vaadin-Flow-artiges Komponentenmodell
für:
- Component Tree
- Properties
- Events
- inkrementelle UI-Synchronisation
### Tauri-artige System-WebView-Nutzung
für:
- kleines Packaging
- schnelles Startup
- HTML/CSS-Rendering ohne eingebettetes Chromium
Das Ziel ist eine Desktop-Anwendung, die sich für den Entwickler wie eine normale Kotlin-Anwendung anfühlt:
```text
Kotlin
↓
Keluna
↓
System WebView
↓
Native Desktop
```
Der Browser ist dabei kein Teil der Anwendungsarchitektur.
Er ist lediglich der Renderer.
**Keluna – Kotlin Embedded Local UI for Native Applications.**