Skip to content

xdsswar/jux-toolkit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Jux Toolkit

Jux Toolkit

Build desktop apps with Java + HTML/CSS/JS — powered by native webviews.

A JavaFX-inspired application framework backed by the OS's native WebView
(WebView2 on Windows, WebKit on macOS, WebKitGTK on Linux).
Panama FFI. Virtual threads. Zero bundled Chromium.

Work in Progress Cross-platform (Windows development first) Java 25 Gradle 9 Rust wry tao License


Windows only (for now) — macOS and Linux support coming soon

WARNING: WORK IN PROGRESS

Jux Toolkit is a personal invention born from my own ideas and experimentation. It is currently in active development and is NOT production-ready. You will encounter bugs, missing features, and rough edges -- that's expected at this stage. The API is actively evolving: signatures, behavior, and module structure may change between versions as issues are discovered and fixed, and as the developer experience is refined to make things simpler and more intuitive to use. If something feels wrong or broken, it probably is, and it's likely already on the roadmap to improve. Use at your own risk, and expect breaking changes as the project matures.

Platform support: Jux is designed to be cross-platform (Windows, macOS, Linux). Development and testing are currently focused on Windows first. macOS and Linux support are coming soon.


Screenshots

Jux Toolkit — Dark Theme

Dark theme — built entirely with HTML, CSS, and JavaScript rendered in a native webview.


Jux Toolkit — Light Theme

Light theme — same application, zero code changes. Just CSS.


Jux Toolkit — Multi-Window

Multi-window — independent secondary windows, each with its own webview, IPC, and event loop.


Jux Toolkit — Robot Desktop Automation

Robot — desktop automation with live magnifier, screen capture, pixel color, mouse/keyboard control. All via Rust FFI, no AWT/Swing.


The Entire Web Ecosystem at Your Fingertips

Forget the limitations of traditional Java UI toolkits. With Jux, your desktop application's interface is a real browser engine — the same one that powers billions of web pages. That means you get instant access to the entire web frontend ecosystem:

  • Tailwind CSS — utility-first styling, dark mode, responsive layouts, all the classes you already know
  • Bootstrap — drop in a CDN link and you have a complete component library with grids, modals, tooltips, and carousels
  • React, Vue, Svelte, Angular — build your UI with any modern framework, then serve it through Jux
  • Three.js / D3.js / Chart.js — 3D graphics, data visualizations, and interactive charts — right inside your desktop app
  • Lottie / GSAP / Framer Motion — buttery-smooth animations that would take months to implement in Swing or JavaFX
  • Google Fonts / Font Awesome / Lucide Icons — thousands of fonts and icon sets, one <link> tag away
  • Monaco Editor / CodeMirror — embed a full VS Code-grade code editor in your app in minutes
  • Markdown renderers, PDF viewers, syntax highlighters, rich text editors — if it works in a browser, it works in Jux

This is the fundamental advantage: you are not learning a new UI framework. You are using the web — the most mature, most documented, most ecosystem-rich UI platform ever created — and driving it from Java with full type safety, observable properties, and virtual threads.

Your designers can use Figma and export directly to HTML/CSS. Your frontend devs can use their existing skills. Your Java backend logic stays in Java where it belongs. No compromises.

"Any UI you can build in a browser, you can ship as a native desktop app with Jux."


Built on Tauri — Thank You!

The native layer of Jux Toolkit is entirely built on top of the amazing Tauri ecosystem — specifically the wry (webview) and tao (windowing) crates. None of this would be possible without the incredible work of the Tauri developers — they are some of the best engineers in the open-source community. Their cross-platform webview abstraction and robust event loop are the backbone that powers every Jux window. A massive thank you to the entire Tauri team for making projects like this possible.


What is Jux?

Jux Toolkit lets you write desktop applications in Java with a web-based UI. Your business logic, IPC handlers, and window management live in Java. Your interface is HTML + CSS + JavaScript rendered by the platform's native webview. Communication flows over a typed JSON IPC channel with Java handlers running on virtual threads.

Think of it as JavaFX meets Tauri — the developer experience of extend Application, override start(Window), call launch(), but rendering with a real browser engine instead of JavaFX's Prism pipeline.

Why Jux?

Jux Toolkit Electron JavaFX
Binary size ~2 MB (system webview) ~150 MB (bundled Chromium) ~40 MB (JFX runtime)
Rendering Native WebView2/WebKit Chromium Prism/OpenGL
DevTools Full browser DevTools Full browser DevTools Scenic View (limited)
Language Java + HTML/CSS/JS JS/TS + HTML/CSS Java + FXML/CSS
Threading Virtual threads (JDK 25) Node.js event loop Platform thread
Memory Low (no bundled engine) High Medium

Quick Start

public class HelloApp extends Application<Window> {

    @Override
    public void start(Window window) throws Exception {
        window.setTitle("Hello Jux");
        window.setSize(800, 600);
        window.center();

        // Register a command callable from JavaScript
        window.command("greet", msg -> {
            String name = msg.get("name", String.class);
            return IpcResponse.ok("Hello, " + name + "!");
        });

        // Load your web UI
        window.loadHtml("""
            <!DOCTYPE html>
            <html>
            <body>
                <h1>Hello from Jux!</h1>
                <button onclick="greet()">Click me</button>
                <p id="result"></p>
                <script>
                    async function greet() {
                        const res = await __jux.invoke('greet', { name: 'World' });
                        document.getElementById('result').textContent = res;
                    }
                </script>
            </body>
            </html>
        """);

        window.show();
    }

    public static void main(String[] args) {
        launch(HelloApp.class, args);
    }
}

Architecture

                  Your Java Application
                         |
           +-------------+-------------+
           |             |             |
        jux-ui        jux-dom       jux-net      jux-robot
      (Window,      (Document,    (Request/     (Mouse,
     Application,    Element,     Response     Keyboard,
       IPC)          Events)    Interception)  Screen Capture)
           |             |             |             |
           +------+------+------+------+------+------+
                  |             |
               jux-core      jux-base
             (Platform,    (Properties,
            Native Load)   Collections,
                            Bindings)
                  |
           Panama FFI (java.lang.foreign)
                  |
         C ABI (Rust cdylib)
                  |
    wry + tao + enigo + xcap + WebView2/WebKit
                  |
           OS APIs / Webview

Modules

jux-base — Observable Foundation

Pure Java, zero dependencies. Provides a full JavaFX-style observable properties and collections system.

Properties — typed, observable, bindable:

SimpleStringProperty name = new SimpleStringProperty("World");
name.addListener((obs, oldVal, newVal) -> {
    System.out.println("Changed: " + oldVal + " -> " + newVal);
});
name.setValue("Jux"); // fires listener

// Binding
SimpleStringProperty greeting = new SimpleStringProperty();
greeting.bind(Bindings.createStringBinding(
    () -> "Hello, " + name.getValue() + "!",
    name
));
// greeting.getValue() == "Hello, Jux!"

Observable Collections — fine-grained change tracking:

ObservableList<String> items = JuxCollections.observableArrayList();
items.addListener((ListChangeListener.Change<? extends String> c) -> {
    while (c.next()) {
        if (c.wasAdded()) System.out.println("Added: " + c.getAddedSubList());
        if (c.wasRemoved()) System.out.println("Removed: " + c.getRemoved());
    }
});
items.addAll("Alpha", "Beta"); // prints: Added: [Alpha, Beta]

Available types: StringProperty, IntegerProperty, LongProperty, DoubleProperty, FloatProperty, BooleanProperty, ObjectProperty<T> — each with Simple*, ReadOnly*, and ReadOnly*Wrapper variants.

Collections: ObservableList<E>, ObservableMap<K,V>, ObservableSet<E>, with JuxCollections factory and Bindings utility class.


jux-core — Platform & Native Loading

Detects OS and architecture, extracts the native library + launcher from the JAR to ~/.jux-toolkit/lib/, and loads it via System.load().

Platform.getOS();      // WINDOWS, MACOS, LINUX, UNKNOWN
Platform.getArch();    // X86_64, AARCH64, UNKNOWN
Platform.isWindows();  // true/false
Platform.isMacOS();    // true/false
Platform.isLinux();    // true/false

Also provides the shared exception hierarchy (JuxException, JuxNativeException, JuxIpcException, etc.) and the @Component annotation for DOM components.

UI thread management lives in jux-ui's Platform class:

Platform.runLater(() -> window.setTitle("Updated"));
Platform.runAndWait(() -> window.setSize(800, 600));
Platform.isJuxThread();       // true if on the event loop thread
Platform.isBackgroundThread(); // true if NOT on UI thread
Platform.checkJuxThread();    // throws if not on UI thread
Platform.isInitialized();     // check toolkit state
Platform.isImplicitExit();    // check implicit exit setting
Platform.setImplicitExit(false); // keep running for tray apps
Platform.exit();              // request application exit

jux-dom — DOM API & Events

Manipulate the browser DOM from Java with a rich, typed API. Selector-based queries, typed element interfaces, a JavaFX-style event system, and a powerful HTML builder pattern.

Document & Element:

Document doc = window.getDocument();

// Query and manipulate
doc.getElementById("title").setInnerText("Hello!");
doc.select(".card").addClass("active");
doc.querySelector("input").setAttribute("placeholder", "Search...");

// Typed element access
Input input = doc.getElementById("email").as(Input.class);
input.setValue("user@example.com");
input.setPlaceholder("Enter email");

// DOM manipulation
doc.getElementById("list").appendHtml("<li>New item</li>");
doc.querySelector(".old").remove();

HTML Builder — Build UI Trees Declaratively:

// Create detached elements in memory, inject once
Element card = doc.create("div").className("card", "shadow").children(
    doc.create("h2").text("User Profile"),
    doc.create("p").text("Welcome back!"),
    doc.create("button")
        .className("btn", "btn-primary")
        .text("Edit Profile")
        .onClick(e -> editProfile())
);
doc.byId("content").setInnerHtml(card);

// Build forms with events, accessibility, and validation
Element form = doc.create("form").className("login-form").children(
    doc.create("input").id("email")
        .attr("type", "email").attr("placeholder", "Email")
        .boolAttr("required").onInput(e -> validate()),
    doc.create("button").attr("type", "submit")
        .text("Sign In").onClick(e -> submit())
);

// Build tables from data
Element table = doc.create("table").children(
    doc.create("thead").children(
        doc.create("tr").children(
            doc.create("th").text("Name"),
            doc.create("th").text("Email")
        )
    ),
    doc.create("tbody").children(
        users.stream().map(u -> doc.create("tr").children(
            doc.create("td").text(u.name()),
            doc.create("td").text(u.email())
        )).toArray(Element[]::new)
    )
);

Convenience Builder Methods:

// Concise shorthand for common operations
doc.create("div")
    .id("progress")
    .className("bar", "animated")
    .style("width", "75%")
    .role("progressbar")
    .aria("valuenow", "75")
    .data("status", "loading")
    .title("75% complete")
    .tabIndex(0)
    .draggable(true)
    .contentEditable(false);

Events — Three ways to register:

// 1. Type-safe EventType constants (full control, returns EventRegistration)
EventRegistration reg = doc.byId("btn").addEventHandler(MouseEvent.CLICK, e -> save());
reg.remove(); // can remove later

// 2. String-based (jQuery-style, concise)
element.on("click", e -> save());

// 3. Typed convenience methods (most concise, fully typed)
element.onClick(e -> save());
element.onKeyDown(e -> { if ("Enter".equals(e.getKey())) submit(); });
element.onInput(e -> updatePreview(e.getValue()));
element.onMouseEnter(e -> showTooltip());
element.onScroll(e -> handleScroll(e.getElementScrollTop()));
element.onDragStart(e -> beginDrag(e));

Event type hierarchy:

Event.ROOT
 +-- DomEvent.ANY
 |    +-- MouseEvent.ANY (CLICK, DBLCLICK, MOUSEDOWN, MOUSEUP, MOUSEMOVE, ...)
 |    +-- KeyEvent.ANY (KEYDOWN, KEYUP, KEYPRESS)
 |    +-- InputEvent.ANY (INPUT, CHANGE)
 |    +-- FocusEvent.ANY (FOCUS, BLUR, FOCUSIN, FOCUSOUT)
 |    +-- ScrollEvent.ANY (SCROLL)
 |    +-- DragEvent.ANY (DRAGSTART, DRAG, DRAGEND, DRAGOVER, DROP)
 +-- WindowEvent.ANY (SHOWN, HIDDEN, CLOSE_REQUEST, FOCUSED, RESIZED, MOVED, ...)

Typed elements: Input, Image, Form, Anchor, Select, Video, Canvas — each with element-specific methods.

Web APIs from Java: LocalStorage (getItem/setItem/removeItem), Console (log/warn/error/table/time), DomTransaction (batched writes).

Component system:

@Component(path = "components/sidebar.html")
public class Sidebar extends JuxComponent {
    @Override
    protected void onMount(Element root, Document document) {
        document.byId("nav-home").onClick(e -> navigate("home"));
    }
}

document.setContent("sidebar", new Sidebar());

jux-net — Network Interception

Intercept, modify, or block HTTP requests and responses made by the webview.

// Log all requests
window.getNetworkInterceptorChain().addRequestInterceptor("logger", request -> {
    System.out.println(request.getMethod() + " " + request.getUri());
    return RequestDecision.proceed(request);
});

// Proxy API calls
window.getNetworkInterceptorChain().addRequestInterceptor("proxy", request -> {
    if (request.getUri().getHost().equals("api.example.com")) {
        request.setUri(URI.create("http://localhost:8080" + request.getUri().getPath()));
    }
    request.setHeader("Authorization", "Bearer " + getToken());
    return RequestDecision.proceed(request);
});

// Block ads
window.getNetworkInterceptorChain().addRequestInterceptor("adblock", request -> {
    if (request.getUri().getHost().contains("ads.")) {
        return RequestDecision.block();
    }
    return RequestDecision.proceed(request);
});

// Modify responses
window.getNetworkInterceptorChain().addResponseInterceptor(response -> {
    response.setHeader("Access-Control-Allow-Origin", "*");
    return response;
});

jux-robot — Desktop Automation

Programmatic mouse, keyboard, and screen control — all via Rust FFI. No java.awt.Robot, no AWT/Swing dependency.

Robot robot = Robot.create();

// Mouse
robot.mouseMove(500, 300);
robot.mouseClick(MouseButton.LEFT);
robot.mouseMoveSmoothly(800, 600, Duration.ofMillis(500));
robot.mouseScroll(0, -3);
robot.mouseDrag(100, 100, 400, 400, MouseButton.LEFT);
MousePosition pos = robot.mousePosition();  // global desktop coordinates

// Keyboard
robot.typeText("Hello, World!");
robot.keyPress(KeyCode.CONTROL_LEFT);
robot.keyType(KeyCode.C);
robot.keyRelease(KeyCode.CONTROL_LEFT);

// Screen capture
ScreenCapture capture = robot.captureScreen();         // full primary monitor
ScreenCapture region = robot.captureRegion(x, y, w, h); // any region, any monitor
Color pixel = robot.pixelColor(500, 300);               // works across all monitors
capture.saveAsPng(Path.of("screenshot.png"));
byte[] pngBytes = capture.toPngBytes();                 // in-memory PNG encoding

// Monitor enumeration
List<ScreenInfo> monitors = robot.screens();

// Live magnifier — continuously captures area around cursor
MouseCaptureBox box = MouseCaptureBox.builder()
    .captureSize(80, 80)
    .frameRate(20)
    .build();
box.start(robot, (frame, error) -> {
    String png = frame.toBase64Png();   // high-quality PNG for display
    Color center = frame.centerColor(); // pixel under cursor
});
box.stop();

jux-ui — Application Framework

The top-level module. Contains Application, Window, Dialog, and all native FFI access. This is the only module that calls native code directly. Window and Dialog both extend an internal BaseWindow class that provides core infrastructure (handles, properties, webview, IPC, events).

Window — fully property-driven:

public void start(Window window) {
    // All state is observable
    window.setTitle("My App");
    window.setSize(1024, 768);
    window.center();
    window.setResizable(true);
    window.setAlwaysOnTop(false);

    // React to state changes
    window.titleProperty().addListener((obs, old, title) ->
        System.out.println("Title: " + title));
    window.widthProperty().addListener((obs, old, w) ->
        System.out.println("Width: " + w));
    window.focusedProperty().addListener((obs, old, focused) ->
        System.out.println("Focused: " + focused));

    // Bind properties
    SimpleStringProperty appTitle = new SimpleStringProperty("My App");
    window.titleProperty().bind(appTitle);
    appTitle.setValue("Updated"); // window title updates automatically

    // Window events
    window.addEventHandler(WindowEvent.CLOSE_REQUEST, event -> {
        event.consume(); // prevent close
        showConfirmDialog();
    });

    // DevTools
    window.setDevToolsEnabled(true);
    window.openDevTools();

    window.show();
}

IPC — Java commands callable from JavaScript:

// Java side — manual extraction
window.command("save-user", msg -> {
    String name = msg.get("name", String.class);
    int age = msg.get("age", Integer.class);
    db.save(new User(name, age));
    return IpcResponse.ok(Map.of("saved", true));
});

// Java side — POJO databinding (Jackson Databind, auto-loaded)
window.command("save-user", msg -> {
    User user = msg.as(User.class);       // JSON -> POJO
    db.save(user);
    return IpcResponse.ok(user);           // POJO -> JSON
});

// Typed messaging — receive POJOs directly
window.on("user:created", User.class, (User user) -> {
    System.out.println("New user: " + user.getName());
});

// JavaScript side
const result = await __jux.invoke('save-user', { name: 'Alice', age: 30 });
console.log(result.saved); // true

Push events from Java to JavaScript:

// Java: push data to the browser
window.emit("stats-update", """
    {"cpu": 42, "memory": 68}
""");

// JavaScript: listen for events
__jux.listen('stats-update', (data) => {
    document.getElementById('cpu').textContent = data.cpu + '%';
});

Custom chrome (frameless window with snap layout support):

window.setCustomChrome(true);
window.setTitleBarHeight(40);
window.setDragControl("titlebar");      // draggable caption area
window.setMinimizeControl("btn-min");
window.setMaximizeControl("btn-max");   // Windows 11 snap layouts work automatically
window.setCloseControl("btn-close");

Dialogs:

// Custom dialog with typed result
Dialog<String> dialog = new Dialog<>(window);
dialog.setTitle("Enter Name");
dialog.setSize(400, 300);
dialog.loadResources("/web/dialogs", "name-input.html");
dialog.command("submit", msg -> {
    dialog.setResult(msg.get("name", String.class));
    dialog.close();
    return IpcResponse.ok();
});
Optional<String> name = dialog.showAndWait();

// Native file dialogs
Optional<Path> file = new FileDialogBuilder()
    .title("Open Project")
    .addFilter("Java Files", "java", "jar")
    .openFile();

// Native message dialogs
MessageDialog.info("Success", "File saved.");
boolean ok = MessageDialog.confirm("Delete?", "This cannot be undone.");

System tray, menus, plugins — all supported. See the architecture guide for complete API docs.

Multi-window — independent windows at runtime:

Each secondary window has its own webview, IPC channel, event loop, and OS thread:

// Create a secondary window on a virtual thread
Thread.ofVirtual().name("settings-window").start(() -> {
    Window settings = new Window();
    settings.setOwner(primaryWindow);  // z-ordering, auto-close with owner
    settings.setTitle("Settings");
    settings.setSize(500, 400);
    settings.initWebView(true);
    settings.loadHtml(settingsHtml);

    // Per-window IPC — isolated from other windows
    settings.command("save", msg -> {
        saveSettings(msg.as(Settings.class));
        return IpcResponse.ok();
    });

    settings.show();  // blocks until window closes
});

// Track all open windows
Window.getWindows().addListener((ListChangeListener<Window>) change ->
    System.out.println("Open windows: " + Window.getWindows().size()));

// Typed dialogs with virtual-thread-friendly showAndWait()
Dialog<String> dialog = new Dialog<>(primaryWindow);
dialog.setTitle("Enter Name");
dialog.setSize(400, 250);
dialog.initWebView(true);
dialog.loadHtml(formHtml);
dialog.command("submit", msg -> {
    dialog.setResult(msg.getString("name"));
    dialog.dismiss();
    return IpcResponse.ok();
});
Optional<String> name = dialog.showAndWait();  // blocks virtual thread, not UI

Module Dependency Graph

demo (examples)
  |
  +-- jux-ui (api)        <-- top-level user-facing module
  +-- jux-dom (api)
  +-- jux-net (api)

jux-ui                     <-- main module with native FFI access
  +-- jux-dom (api)
  +-- jux-net (api)
  +-- jux-core (api)
  +-- jux-base (transitive via jux-core)

jux-robot                  <-- standalone desktop automation, native FFI
  +-- jux-core (api)
  +-- jux-base (transitive via jux-core)

jux-net
  +-- jux-core (api)

jux-dom
  +-- jux-core (api)

jux-core
  +-- jux-base (api)

jux-base                   <-- foundation, zero dependencies

Native Stack

Jux uses a Rust C ABI crate (c-abi/) compiled as a cdylib. The Java side calls it via Panama FFI (java.lang.foreign). The Rust crate wraps:

Crate Version Purpose
wry 0.49 WebView abstraction (WebView2/WebKit/WebKitGTK)
tao 0.33 Cross-platform windowing & event loop
muda 0.17 Application & context menus
tray-icon 0.21 System tray icons
rfd 0.15 Native file dialogs
enigo 0.3 Cross-platform mouse/keyboard simulation (jux-robot)
xcap 0.0.14 Cross-platform screen capture & monitor enumeration (jux-robot)
cbindgen 0.27 Auto-generates jux.h from Rust

The generated C header (c-abi/include/jux.h) is consumed by jextract to produce the Panama bindings in com.xss.it.jux.ui.ffi.JuxLib.


Project Structure

jux-toolkit/
+-- jux-base/              Observable properties, collections, bindings
+-- jux-core/              Platform detection, native lib loading, shared types
+-- jux-dom/               DOM API, Element hierarchy, events, components
+-- jux-net/               Network request/response interception
+-- jux-robot/             Desktop automation (mouse, keyboard, screen capture)
+-- jux-ui/                Application, Window, Dialog, IPC, native FFI bridge
+-- c-abi/                 Rust C ABI crate (wry + tao)
|   +-- src/               Rust source (app.rs, window.rs, webview.rs, ...)
|   +-- include/jux.h      Generated C header (cbindgen)
|   +-- bin/               Compiled platform binaries
+-- jux-launcher/          Native launcher (C, spawns JVM on non-main thread)
+-- demo/                  Example application
+-- gradle/
|   +-- libs.versions.toml Version catalog
+-- build.gradle           Root build with native + Java orchestration
+-- CLAUDE.md              Full architecture guide

Building

Prerequisites

  • JDK 25 (with preview features)
  • Gradle 9.x
  • Rust (stable toolchain) — for building the native library
  • CMake — for building the native launcher
  • Windows: WebView2 runtime (ships with Windows 10/11)
  • Linux: libwebkit2gtk-4.1-dev
  • macOS: Xcode command-line tools

Build Commands

# Full build: native (Rust + CMake) + Java
./gradlew buildAll

# Java only (uses cached native binaries)
./gradlew build -PskipNative

# Native only (no Java)
./gradlew buildAll -PnativeOnly

# Run the demo
./gradlew :demo:run -PskipNative

# Run tests
./gradlew test

JVM Flags

--enable-preview --enable-native-access=ALL-UNNAMED

These are configured automatically in the demo's build.gradle.


Threading Model

OS Main Thread
  +-- tao/Win32/AppKit/GTK event loop
       +-- Upcalls arrive here -> immediately handed to virtual threads

Virtual Thread Pool
  +-- All IPC command handlers
  +-- All event handlers (window, DOM, lifecycle)
  +-- Free to block: JDBC, HTTP, Files, sleep

Rules:

  1. Never block the event loop thread
  2. IPC commands automatically run on virtual threads
  3. Platform.runLater() schedules work on the UI thread
  4. Observable property listeners fire on virtual threads for native events
  5. All native handles are thread-safe (AtomicLong + PointerRegistry)

Memory Safety

Every native handle is tracked by PointerRegistry — a PhantomReference + ReferenceQueue system that guarantees:

  • Exactly-once destruction via AtomicLong.getAndSet(0)
  • GC safety net — abandoned handles are cleaned up automatically
  • Thread-safe close — concurrent close() from N threads is safe
  • Zero leaks — verified by PointerRegistry.activeCount() in tests

Native types (Pointer, MemorySegment, Arena) never appear in public API. Users interact with Window, Document, Element — never with handles.


Package Naming

Visibility Pattern Contents
Public API xss.it.jux.{module}.* Interfaces, records, builders — what users import
Internal com.xss.it.jux.{module}.* Handles, FFI, memory management — never exported

Enforced by JPMS module-info.java in every module.


Requirements

Component Minimum
Java JDK 25
Gradle 9.x (Groovy DSL)
Rust Stable toolchain
Windows 10+ (WebView2 runtime)
macOS 11+ (WebKit)
Linux WebKitGTK 4.1+

License

Jux Toolkit is dual-licensed:

  • AGPL-3.0 — Free for open-source projects. Your entire application must be open-source under a compatible license. See LICENSE.
  • Commercial License — For proprietary/closed-source applications. See LICENSE-COMMERCIAL.md for details.

Open-source? Use it freely. Building a proprietary app? You need a commercial license.

Copyright (c) 2026 XTREME SOFTWARE SOLUTIONS.


Built with Panama FFI, virtual threads, and native webviews.

About

Jux Toolkit — Java 25 desktop framework powered by native webviews via Panama FFI. Java + HTML/CSS/JS apps with JavaFX-style APIs, zero JNI.

Resources

License

AGPL-3.0 and 2 other licenses found

Licenses found

AGPL-3.0
LICENSE
Unknown
LICENSE-COMMERCIAL.md
Unknown
LICENSE-HEADER.txt

Stars

30 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors