Goldberry
The GPU lane, canvas3d and 4K60 video →

Build fast, lightweight desktop apps in no time.

Goldberry is an open-source, declarative UI toolkit for Java 25+. A window is three lines, a screen is a KDL file that reloads while it runs, and the same code runs as a plain jar on any JDK or compiles with GraalVM into one native binary. No JNI, no bundled web engine. Apache 2.0.

v2026.1 calendar versions: YEAR.RELEASE · Open source · Apache 2.0

HarfBuzzshaping Yogalayout Blend2Draster SDL3present screen.kdl theme.css App.java Linux Windows macOS Goldberry

Built on

See it running

The showcase is one widget tree in a single window. These are the toolkit's own golden images, the frames its tests compare against.

goldberry-showcase1200 × 900, the toolkit's own golden images · hover to magnify
Goldberry showcase: Controls. Buttons, toggles, radios, sliders, badges and chips, drawn to the design system's metrics.
Controls. Buttons, toggles, radios, sliders, badges and chips, drawn to the design system's metrics.

Fast to start, fast to build, light to ship

A desktop UI toolkit for Java that owns its whole pipeline, from the stylesheet to the pixel, so nothing sits between your code and the window.

Read the book

Declarative

Describe the screen. The toolkit keeps it true.

A widget is an immutable Java record with a pure build(), or the same tree as a KDL node. The element tree behind it persists, so state and :hover survive a parent re-describing its child.

  • Every widget is a record, a node and a CSS type
  • Markup names an action and a value to bind to; it never contains code
  • A typo fails at inflation, not silently at a click
Read about widgets →
The Goldberry showcase: buttons, toggles, radios, sliders, badges and chips

Real CSS, real flexbox

Style it like the web. Reload it while it runs.

A genuine CSS subset with variables, cascade and transitions, laid out by Yoga. Every colour is a --gb-* token, so a theme switch restyles controls whose rules never mention one. Stylesheets and markup hot-reload.

  • Nord light and dark out of the box
  • Regular and compact density that no widget mentions
  • Transitions on a frame clock, deterministic in tests
Read about styling →
The showcase's forms screen in the light theme

Light to ship

A jar on any JDK 25+, or one native binary with GraalVM.

The same application runs as a plain jar, with the native library in a classifier jar, or compiles with GraalVM native image into one 41 MiB executable with that library inside it. Frames are rasterized on the CPU, so plain UI needs no GPU context, and only the damaged region is repainted.

  • No JNI and no third-party Java dependencies
  • Linux, Windows and macOS behind one SDL3 backend
  • A GPU lane, video and audio, and a web view as optional modules
Read about native image →
The showcase's charts screen: line, bar, area and donut charts

Easy setup, instant window

Any JDK 25+, one BOM, and a window on screen before the coffee is poured. GraalVM is a third step, and an optional one.

1 · Build file

Add the dependency

The BOM pins the version; the goldberry artifact brings common, natives, core and widgets. The native library arrives as classifier jars, one per platform you run on.

repositories {    mavenCentral()}dependencies {    implementation platform('io.github.digitalsmile:goldberry-bom:2026.1')    // common, natives, core and widgets in one    implementation 'io.github.digitalsmile:goldberry'    // optional: Markdown and HTML, video and audio, the GPU lane    implementation 'io.github.digitalsmile:goldberry-html'    // the native library, one classifier per platform you run on    runtimeOnly 'io.github.digitalsmile:goldberry-natives::linux-x64'    runtimeOnly 'io.github.digitalsmile:goldberry-natives::linux-aarch64'    runtimeOnly 'io.github.digitalsmile:goldberry-natives::macos-aarch64'    runtimeOnly 'io.github.digitalsmile:goldberry-natives::windows-x64'}

2 · Plain Java

Open a window on any JDK 25+

Three lines. No backend to name, no event loop to write. Runs as an ordinary jar; nothing to install beyond the jars themselves.

var window = Window.open("Hello", 960, 640);window.onPaint(frame -> frame.fill(0xFF2E3440));Goldberry.run();// Work that is not instant goes off the UI thread// and comes back on it:Goldberry.async(() -> loadTheThing())         .thenAccept(thing -> window.title(thing.name()));

3 · Optional: GraalVM

Compile to one native binary

The same application, compiled ahead of time with GraalVM native image. One executable, the native library inside it, no JDK on the user's machine.

# Optional. Needs a GraalVM for Java 25+; the result needs nothing../gradlew :example:nativeImage -Pgraalvm.home=/path/to/graalvm# One self-contained file, the native library inside it../example/build/native/goldberry-showcase-linux-x64

79 names a KDL file can use today

actionaudio-playerbreadcrumbscanvas3dcheckboxcollapsecrumbdonut-chartformhudknoblistmasonrymenuoptionpointqr-coderowselectskeletonsparklinestackstepstabstext-inputtogglewizardactionaudio-playerbreadcrumbscanvas3dcheckboxcollapsecrumbdonut-chartformhudknoblistmasonrymenuoptionpointqr-coderowselectskeletonsparklinestackstepstabstext-inputtogglewizard
affixbadgebuttoncardchipcolor-pickerdate-pickerentrygroup-boximageline-chartmarkdown-viewmedia-controlsmenubarpagepopoverradioscrollseparatorsliderspinnerstatistictabtexttime-pickertreeaffixbadgebuttoncardchipcolor-pickerdate-pickerentrygroup-boximageline-chartmarkdown-viewmedia-controlsmenubarpagepopoverradioscrollseparatorsliderspinnerstatistictabtexttime-pickertree
area-chartbar-chartcanvascarouselcode-inputcolumndialogfieldhtml-viewitemlinkmarkermedia-playermessagepanelprogressradio-groupsegmentedseriesspacersplit-panesteptabletext-areatimelinevideo-viewarea-chartbar-chartcanvascarouselcode-inputcolumndialogfieldhtml-viewitemlinkmarkermedia-playermessagepanelprogressradio-groupsegmentedseriesspacersplit-panesteptabletext-areatimelinevideo-view

And everything else in the box

Pure Java over FFM

Hand-written Foreign Function & Memory bindings on Java 25+.

  • No JNI and no third-party Java dependencies
  • One statically linked native library
  • JPMS keeps raw memory inside the natives module

Three platforms, one SPI

Linux, Windows and macOS are peer platforms from the first commit.

  • Wayland and X11, through a single SDL3 backend
  • Fractional DPI correct by construction
  • A headless backend for CI and servers

Text, icons and emoji

Typography is part of the toolkit, not something the platform decides.

  • HarfBuzz shaping with Inter and JetBrains Mono embedded
  • 1544 Lucide icons bundled
  • Noto Color Emoji as an opt-in module, drawn from its paint graphs

Video and audio

goldberry-media drives FFmpeg from Java; audio leaves through SDL, video is a widget.

  • Hardware decode, track switching, subtitles, network streams
  • Royalty-free codecs built in; bring your own through a decoder SPI
  • 4K60 with every picture shown when the GPU module is present

A GPU when you want one

The CPU path never needs a GPU context. goldberry-gpu adds one, bound to SDL_GPU.

  • Windows composite through the GPU by default, and fall back to the CPU
  • canvas3d: a GPU layer your own renderer draws into
  • Shaders in HLSL, compiled and committed

A web page, when the platform has one

web-view drives the desktop's own engine through a separate optional library.

  • WebKitGTK, WebView2 and WKWebView
  • Never a load-time dependency of the toolkit
  • Ask Goldberry.capabilities() for WEB_VIEW before offering one

Plain-Java models

@Model, @Bind and @Action make ordinary field assignments observable.

  • A jar binds at run time through the annotations
  • A build-time weaver prepares the same model for native image
  • No annotation processor, no code generation step

Content widgets, tested in pixels

Markdown, HTML and charts render as ordinary widgets, with no browser engine underneath.

  • markdown-view and html-view, first-party charts
  • Golden images per platform
  • A virtual frame clock makes animation deterministic

Starts fast. Runs fast.

Numbers from the repository's own traces and benchmarks, in milliseconds and microseconds.

Starts fast

The README's own start-up trace, on a plain JDK. The first line is the JVM; the last three are the toolkit.

  • 534 msthe JVM startingbefore any Goldberry code runs
  • 26 msnative library mappedone static library, bound through FFM
  • 163 msSDL video subsystem upwindow, input and display ready
  • 117 msfirst frame presentedabout 330 ms of toolkit work in total

With GraalVM native image the first line is the one that changes: there is no JVM to start and no classes to load, so the executable reaches its first frame after the toolkit's own work.

Runs fast

Per frame, once the window is up.

  • 3.1 msmedian frame960×640 with a wrapped paragraph, paced to the display; 4.3 ms at the 95th percentile
  • 2.3 msa full 4K raster3840×2160, Blend2D across four paint workers
  • 117 µsrepainting one changeonly the damaged region is drawn again
  • 9 µsa frame where nothing changedlayout and tree walk on the retained element tree

Measured on one Linux machine. The three-platform run of the same benchmarks is in progress. Details

Widgets are the heart of the toolkit

A design system, not a theme file

Nord's sixteen colours alias into --gb-* tokens; everything else is metrics the widgets obey: a 4 px ramp, a type scale, two densities, three materials and a motion scale. Switch the theme and every control restyles, though no widget's rule names a colour.

AaAaAaInter · 400 500 600
{ }JetBrains Mono
4 px ramp
Regular · 32Compact · 28
Themes
Nord light and Nord dark, switchable at run time
Type
Inter and JetBrains Mono embedded; body 13/18, a fixed scale above it
Density
regular (32 px controls) and compact (28 px), set once per window
Materials
opaque, frost and veil, with an automatic opaque fallback
Motion
100 / 160 / 240 ms durations; enters ease out, exits are faster than enters
Icons
1544 Lucide icons and Noto Color Emoji, both as widgets
Scrollbars
one spec for the whole scroll family, overlay and classic
The design system →

Styled in CSS, the real one

Variables, cascade, pseudo-classes and transitions, laid out by Yoga flexbox. A stylesheet names tokens, never colours, and reloads while the application runs. The class on a KDL node is the whole contract with it.

/* Alias tokens: the only place a colour is named. */:root {  --gb-accent: var(--nord10);  --gb-surface: var(--nord1);  --gb-text: var(--nord4);  --gb-button-bg: var(--nord3);  --gb-button-danger-bg: var(--nord11);}

How it compares

Where Goldberry sits next to the other ways of putting a window on screen from the JVM.

Goldberry on a JDKGoldberry, GraalVM nativeJavaFXSwingCompose for DesktopSWT
LanguageJava 25+Java 25+JavaJavaKotlinJava
LicenceApache 2.0Apache 2.0GPL v2 + Classpath exceptionGPL v2 + Classpath exceptionApache 2.0EPL 2.0
UI modelDeclarative: immutable records with a pure build(), or KDL markupSameScene graph; imperative or FXMLImperative component treeDeclarative @Composable functionsImperative, native widgets
MarkupKDL, hot-reloaded while runningKDL, hot-reloaded while runningFXMLNoneNone, code onlyNone
Styling and layoutA real CSS subset and Yoga flexboxSameJavaFX CSS dialect (-fx-*), layout panesLook and Feel, layout managersKotlin modifiersPlatform look, layout managers
RenderingOwn pipeline: Blend2D on the CPU; GPU composition and canvas3d optionalSamePrism, GPU with software fallbackJava2DSkia (Skiko), GPUThe platform toolkit: GTK, Win32, Cocoa
TextHarfBuzz shaping; Inter and JetBrains Mono embedded; colour emojiSamePlatform shaping through PrismJava2DSkiaPlatform
What you shipYour jars plus the goldberry-natives classifier jar; any JDK 25+One executable, no JDK, about 41 MiB for the whole showcasejlink runtime or jpackage with a JDK insidejpackage with a JDK insidejpackage with a JDK insidejpackage with a JDK inside
Start-upJVM start, then about 330 ms of toolkit work to the first frameThe toolkit's work only; no JVM to startJVM start, then the FX runtimeJVM start, then AWTJVM start, then SkikoJVM start, then the platform toolkit
GraalVM native imageOptionalFirst-class: the binding schema and the weaver are designed for itThrough GluonFXPartial AWT support, not on every platformCommunity experiments onlyCommunity experiments only
Native codeOne static library over FFM, no JNISame, linked into the executableBundled natives over JNIInside the JDKSkiko over JNIJNI into the platform toolkit
Third-party Java dependenciesNoneNoneNone beyond the FX modulesNoneKotlin runtime, Skiko, Compose runtimeNone
PlatformsLinux (Wayland, X11), Windows, macOSSameLinux, Windows, macOS, mobile through GluonLinux, Windows, macOSLinux, Windows, macOSLinux, Windows, macOS
Headless testingHeadless backend, golden images per platform, virtual frame clockSameMonocle, TestFXHeadless AWT, no pixel goldens built inCompose UI testingSWTBot
AccessibilityKeyboard, focus ring, WCAG AA contrast and roles; no screen-reader bridge yetSameYesYesYes, through AWTYes, native

This is how we read each project in September 2026. It will drift; corrections are welcome as an issue.

Questions, answered

What is Goldberry?

An open-source, declarative desktop UI toolkit for Java 25+. Widgets are immutable Java records or KDL markup, styled with a real CSS subset and laid out with Yoga flexbox, drawn by its own rendering pipeline. Licensed under Apache 2.0.

Which Java version does it need?

Java 25 or newer. It uses the Foreign Function & Memory API, so there is no JNI and no third-party Java dependency.

Do I need GraalVM?

No. Goldberry runs as a plain jar on any JDK 25+. GraalVM native image is an optional, supported target that produces one self-contained executable, with the native library inside it.

Which platforms are supported?

Linux (Wayland and X11), Windows and macOS, as peer platforms behind one SDL3 backend. There is also a headless backend for tests and servers.

Does it need a GPU?

No. Frames are rasterized on the CPU with Blend2D across worker threads. The goldberry-gpu module adds GPU composition, a canvas3d layer and GPU video presentation when you want them.

How is it licensed?

Apache License 2.0, with no contributor licence agreement and no commercial edition. The source is on GitHub at DigitalSmile/goldberry.

How do I add it to a project?

Add the goldberry-bom to Gradle or Maven, then the goldberry artifact plus the goldberry-natives classifier jars for the platforms you run on. Coordinates are under io.github.digitalsmile.

What landed lately

  1. The GPU lane: composition, canvas3d and 4K60 video

    goldberry-gpu binds SDL_GPU. Windows composite through the GPU by default and on the CPU where they cannot, canvas3d is a layer an application renders into, and video-view shows its pictures through a GPU layer: 4K60 with every picture shown.

  2. goldberry-media: FFmpeg driven from Java

    Audio and video playback with hardware decode, track switching, text subtitles, network streams read through a cache, and the operating system's own decoders behind the Decoder SPI.

  3. Upstreams moved

    Blend2D 0.21.3, HarfBuzz 14.5.0, SDL 3.4.16, md4c 0.6.0 and Gradle 9.7.1. The emoji face is now Noto Color Emoji, shipped as goldberry-emoji and drawn from its paint graphs.

  4. Snapshots on every push

    Every push to master publishes the next line's -SNAPSHOT of the toolkit, the BOM and the optional modules to the Central Portal snapshot repository.

Open source, Apache 2.0, yours to build on.

Add the BOM, open a window, and describe the rest in KDL and CSS. No CLA, no commercial edition, no telemetry.

Download the showcase

One self-contained GraalVM native binary per platform. No JDK needed. Binaries are attached to each release tag; the buttons open the releases page.