Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Concept

Goldberry draws every pixel itself, describes a screen as data, and keeps the native code behind one boundary. This page is the idea in five parts and what each one buys.

One rendering pipeline, everywhere

Goldberry does not wrap the platform’s widgets and does not embed a browser. A button on Linux, Windows and macOS is the same button: the same CSS rule, the same Yoga layout, the same Blend2D rasterization, the same HarfBuzz-shaped text in the same embedded fonts. The platform supplies a window, input events, the clipboard and a surface to present into, through SDL3. Everything above that line is Java and runs identically on every desktop.

The result is deterministic. A frame is the same bytes on every machine, which is what lets the toolkit test itself with golden images and lets an application do the same (ADR-0002, ADR-0003).

A screen is a description

A widget is an immutable Java record with a pure build(). The toolkit calls build(), diffs the result against the element tree it kept from the last frame, and updates only what changed. State that must survive a rebuild, a hover or a caret, lives on the element rather than on the widget (ADR-0004, ADR-0052).

The same tree can be written as KDL markup, and every built-in widget exists three ways: a record, a node name and a CSS type (ADR-0059).

row id="confirm" {
  spacer
  button press="dismiss" "Cancel"
  button class="danger" press="delete" "Delete"
}
new Row(
        new Spacer(),
        new Button("Cancel", this::dismiss),
        new Button("Delete", this::delete).styled("danger")
)

Markup names things and never contains code. A press= names an action, a bind= names a value, an icon= names an icon. Each resolves against a registry the application supplied, and a name that resolves to nothing fails when the document is inflated rather than when the user clicks (ADR-0062).

Data flows down, events flow up

A control never owns its value. It is handed an Observable and draws what it reads. When the user acts, the control raises an action, the application’s handler assigns a field, and the new value flows back down. A checkbox whose tick will not move is a handler that did not change the state, which is where the bug is (ADR-0063).

The model is plain Java: a class of fields marked @Bind, and methods marked @Action. On the JVM the toolkit binds them reflectively at run time. For a native image a build step rewrites the compiled class so that every assignment notifies directly, with no reflection anywhere (ADR-0155). Model weaving is the whole story.

Real CSS, real flexbox

Styling is a genuine subset of CSS: selectors, the cascade in layers, custom properties, inheritance, transitions on a frame clock, transforms and opacity. Layout is flexbox, through Yoga bound directly rather than reimplemented (ADR-0005).

Every colour a control uses is a --gb-* token, so switching from the Nord dark theme to the Nord light one restyles every control though no rule names a colour. Density is three tokens on :root. Markup and stylesheets hot-reload while the application runs (Styling).

Light to ship

The toolkit has no third-party Java dependencies. The native libraries are statically linked into one libgoldberry per platform, shipped as a classifier jar and bound through hand-written FFM calls that live in one module (ADR-0007, ADR-0010).

An application runs as a plain jar on any JDK 25, or compiles with GraalVM into one executable with the library inside it. The native showcase is 41 MiB, opens its window in about 120 ms and paints a headless frame in about a millisecond (Native image, ADR-0506).

What it is built on

LibraryRoleWhere it lives
Blend2D2D rasterization, with its PNG, JPEG and QOI codecsinside libgoldberry
Yogaflexbox layoutinside libgoldberry
HarfBuzztext shapinginside libgoldberry
SDL3windows, input, clipboard, popups, tray, SDL_GPUinside libgoldberry
md4cMarkdown parsinginside libgoldberry
libwebpWebP decodinginside libgoldberry
FFmpegaudio and video decodinggoldberry-media, as separate shared libraries
Inter, JetBrains Monothe UI and code typefacesinside goldberry-core
Lucide1544 icons as path datainside goldberry-core
Noto Color Emojithe emoji facegoldberry-emoji

Everything in the table is open source, and the licences travel inside every jar under META-INF/ (ADR-0015).