English
GitHub
Theme

Desktop UI for Java

Desktop apps in Java, drawn from scratch.

Limn draws its own pixels. Widgets, layout, text, charts, media and a 3D viewport, in one dependency, with no Swing, no JavaFX and no native toolkit underneath.

JDK 17 · Windows, macOS, Linux · Apache-2.0

Built in the open with Claude Code: Claude wrote it, people directed and verified it. What it cost to build is already paid, so you don't have to pay it again. How Limn is built

The demo application, rendered by Limn during this build.
The demo application, rendered by Limn during this build.
The demo application, rendered by Limn during this build.

Try it now

The demo and the theme editor, straight from Maven Central. Nothing to clone; jbang fetches a JDK if you have none. JBang resolves the newest release once and keeps it: add --fresh to take a newer one.

# the showcase
jbang demo@limn-toolkit/limn-toolkit
# the theme editor
jbang theme-editor@limn-toolkit/limn-toolkit
# the showcase
jbang --java-options=-XstartOnFirstThread demo@limn-toolkit/limn-toolkit
# the theme editor
jbang --java-options=-XstartOnFirstThread theme-editor@limn-toolkit/limn-toolkit

Five minutes

One dependency and a main method

No markup language, no annotation processor, no build plugin. Add the backend, which brings the toolkit with it, write plain Java, and you have a window.

Read the install guide
build.gradle.kts
dependencies {
    implementation("io.github.limn-toolkit:limn-backend-lwjgl:1.0.0")
}
pom.xml
<dependency>
  <groupId>io.github.limn-toolkit</groupId>
  <artifactId>limn-backend-lwjgl</artifactId>
  <version>1.0.0</version>
</dependency>
Main.java
import limn.backend.Backend;
import limn.backend.NativeWindow;
import limn.backend.WindowConfig;
import limn.backend.lwjgl.LwjglBackend;
import limn.components.Button;
import limn.components.Label;
import limn.scene.Insets;
import limn.scene.Scene;
import limn.scene.layout.Column;
import limn.scene.layout.Padding;

/** A window with a label and a button that closes it. */
public final class HelloWindow {

    public static void main(String[] args) {
        // macOS needs -XstartOnFirstThread on the JVM command line; it is macOS-only and a
        // JVM elsewhere given it will not start.
        try (Backend backend = new LwjglBackend()) {
            NativeWindow window = backend.createWindow(
                    WindowConfig.of("Hello, Limn", 480, 320));

            Column column = new Column();
            column.gap(12);
            column.add(new Label("A window, drawn by Limn."));
            column.add(new Button("Close").onAction(window::requestClose));

            Scene scene = new Scene(new Padding(Insets.all(24), column));
            scene.bind(window);

            backend.runEventLoop();
        }
    }
}

What you get

A component set you do not have to build

Buttons, fields, lists, tables, trees, date pickers, tabs, menus, dialogs, cards, split panes, a colour picker, bar, line and donut charts, and a virtualized list where a million rows cost what twenty do. Every one of them reads its colour, its shape and its density from the theme, so nothing is hardcoded and a compact mode is one line. Beyond its windows, an application prints to paper or to PDF, keeps an icon in the tray, puts its menus in the macOS menu bar, and drags to and from other programs.

See all of them
Button
Button
ComboBox
ComboBox
Slider
Slider
SegmentedControl
SegmentedControl
Checkbox and switch
Checkbox and switch
Spinner
Spinner

Layout that fits in your head

Six widgets and one marker: a column stacks, a row spreads, a wrap flows onto the next line, a grid lines cells up both ways, a stack overlays, padding insets, and Expanded says who takes the space that is left. Opacity and Transform fade, move, scale and rotate a part of the window without disturbing the layout around it. There is no constraint solver to configure and no layout manager to install.

Read the layout guide
A window laid out with Limn
A window laid out with Limn
A window built from a column, a row, a split and one Expanded.

Forms without a framework

A field is a widget, a validation rule is a listener, and submitting is a method call. Nothing to bind, nothing to register, and validation states that recolour a field the moment the user fixes it.

Read the forms guide
A form built with Limn
A form built with Limn
Captions, validation, a choice and the actions row.

Tables, trees and dates, already built

A table is typed columns over the list your application owns, sorted by the toolkit or by your server, with a footer that sums. A tree is an outline over children you provide, and a row may promise children before it can name them. A date field types an ISO date in the reader's own calendar, and a date picker opens a month grid behind it.

Read the lists guide
A table, a tree and two date widgets in a Limn window
A table, a tree and two date widgets in a Limn window
A table, a tree, a date field and a date picker in one window.

Video and 3D are widgets too

A physically-based 3D viewport and a video player, composited as ordinary widgets: a scroll view clips them, a stack draws over them, and they take part in layout like a label does.

Read the media guide
The Limn 3D viewport
The Limn 3D viewport
The 3D viewport, composited into an ordinary window.

For everyone

Every language, and every screen reader

In your users' languages

Latin, Greek, Cyrillic and CJK mix in one string, and a face is picked for each run of one script. Arabic, Hebrew, Devanagari and Thai are shaped correctly — joined forms, ligatures, marks — and a right-to-left language mirrors the whole window: rows, insets, scrollbars, arrow keys. Input methods compose inside the field, and editing moves by grapheme cluster.

Read the text guide
The same screen captured in Japanese, Simplified Chinese, Korean and Russian, quilted into one window.
The same screen captured in Japanese, Simplified Chinese, Korean and Russian, quilted into one window.
The same screen, captured in four languages during this build.

Read aloud, in those same languages

A screen reader on Windows, VoiceOver on macOS and Orca on Linux read a Limn window through each platform's own accessibility API, with no platform code in your application. Every control describes itself with its role, its name and its state, in the language the interface is displayed in. Naming a control is one call.

Read the accessibility guide
  1. heading“Create your account”
  2. label“Full name”
  3. text field“Full name”label · focusable, editable, required
  4. label“12 / 40”
  5. label“Email”
  6. text field“Email”label · focusable, editable, invalid, required
  7. label“Enter an address like ada@example.com”
  8. label“Password”
  9. password field“Password”label · focusable, editable, password
  10. label“At least 12 characters”
  11. label“Plan”
  12. combo box“Plan”label · focusable, expandable, has-popup
  13. switch“Email me release notes”focusable, checked
  14. separatorhorizontal
The form above, as a screen reader is told about it, captured during this build.

Your identity, not the toolkit's

Your application should look like your product, not like the library it was built with. A theme is plain data (every colour, the corner radius, the size step every control inherits), and one call swaps it at runtime. Load the typeface your brand ships from a file you control, and none of the toolkit's own look survives.

How theming works
The same dense screen of controls rendered seven times side by side, each strip in a different palette, size step and typeface.

The same components, seven themes

Point at a column to see its theme across the whole screen.Tap a column to see its theme; swipe sideways to change.

One screen, seven themes. The code behind every strip is identical.

In the open

How Limn is built

Limn's code is written by Claude, Anthropic's model, in Claude Code, and directed and verified by people. We say so up front because you would want to know.

Directed means every design decision is a written record in docs/adr, argued and accepted before the code. Verified means every change runs against a test suite larger than the code it tests; accessibility is heard rather than assumed, with a screen reader on Windows, VoiceOver on macOS and Orca on Linux reading real windows; and the code has been through repeated audits of correctness, performance and API design.

Getting here took many thousands of model calls and millions of generated tokens. By the COCOMO II cost model, its more than a hundred thousand lines of code, tests not counted, are the work of a team of about twenty people for over two years. That work is done. You can build on it instead of redoing it.

Read the design records

A window on screen in five minutes

The install guide ends with a running program. Everything after that is the guide, the component gallery and the API reference.