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

Architecture

Five layers, three trees and one native boundary. This page is the map an application developer needs. The design document in the repository has the rest.

The authority on the design is docs/ARCHITECTURE.md, with the design system and the per-widget contracts beside it. This page summarises what is built. Where the two differ, the design document says so inline and Status records what shipped.

The layers

┌────────────────────────────────────────────────────────┐
│  Application        Java records, KDL documents, CSS   │
├────────────────────────────────────────────────────────┤
│  Widget layer       widgets → elements → render objects│
├──────────────┬──────────────┬──────────────────────────┤
│  Style        │  Layout      │  Text                   │
│  CSS engine   │  Yoga        │  HarfBuzz + JDK Bidi    │
│  (pure Java)  │  (flexbox)   │  and BreakIterator      │
├──────────────┴──────────────┴──────────────────────────┤
│  Paint and raster   box painter, layers, damage,       │
│                     Blend2D on the CPU, banded threads │
├────────────────────────────────────────────────────────┤
│  Backend SPI        window, present, input, clipboard, │
│                     cursor, tray, popup, GPU surface   │
├────────────────────────────┬───────────────────────────┤
│  SDL3                      │  Headless                 │
│  Linux, Windows, macOS     │  tests and servers        │
└────────────────────────────┴───────────────────────────┘

The application writes the top row. Everything below it is the toolkit, and only the bottom row touches the platform.

The three trees

The widget layer follows Flutter’s model (ADR-0004):

TreeOwned byLifetimeHolds
Widgetsthe applicationone buildan immutable description: a record with a pure build()
Elementsthe toolkitacross rebuildsstate, the subscription a bind= made, who is hovered, focused or pressed
Render objectsthe toolkitacross framesa Yoga node, the box last applied to it, where it was painted

A rebuild produces a new widget tree. The element tree is reconciled against it by type and key, so a parent re-describing its child does not lose the child’s state. The render tree is reconciled against the boxes the elements produce, and every Yoga setter is guarded by a comparison, so a frame in which nothing changed costs a few microseconds (ADR-0069).

The frame loop

One UI thread runs the loop. Blend2D’s workers rasterize in bands beside it.

input events → dispatch (hit-test on the painted frame)
→ rebuild dirty widgets → diff → update elements and render objects
→ style resolution (invalidated nodes only) → Yoga layout (incremental)
→ paint recording → Blend2D raster (banded) → present(buffer, damage)

Three properties of the loop shape what an application sees:

  • It is idle when nothing moves. A frame is asked for by a value that changed, a setState, a transition in flight, or a widget that says it is animating. Nothing polls (ADR-0128).
  • Hit testing reads the painted frame. A pointer event is about what the user can see, so dispatch runs against the snapshot taken while painting rather than a fresh layout (ADR-0054).
  • Only the damage is repainted, where the backend promises the buffer it lends back still holds the last frame (ADR-0072).

Performance has the numbers for each stage.

The native boundary

Every C function the toolkit calls is bound by hand in one module, dev.goldberry.natives, and no raw MemorySegment leaves it. A bound function is a holder class whose method handle is a compile-time constant, which is what makes a call cheap on the JVM and in a native image alike (ADR-0173). A layout probe checks every struct layout and constant against the compiled library at run time, on every platform, so a long that is 32 bits on Windows is caught before it is read (ADR-0029).

The libraries are statically linked into one libgoldberry per platform by a CMake superbuild. Four artifacts exist: linux-x64, linux-aarch64, macos-aarch64 and windows-x64 (ADR-0041).

goldberry-media is the one exception. FFmpeg is LGPL and must stay a set of replaceable shared libraries, so the media module binds it itself, under the same rules (ADR-0461).

The backend SPI

The SPI is the only platform-facing interface. Two implementations exist and the list is closed: sdl3 for every desktop, and headless, which renders to memory for tests and servers (ADR-0041).

The SPI answersHow
a windowlogical pixels in, physical raster out, per-monitor fractional scale
presentthe platform lends a surface and Blend2D draws straight into it (ADR-0046)
inputpointer, wheel in lines, keys and committed text as separate events
a popupa second window with an owner, which a video driver may refuse (ADR-0102)
the clipboardtext as a value, everything else as an offer by MIME type (ADR-0286)
the desktop’s themelight, dark, or the desktop does not say (ADR-0322)
a tray icon, file dialogs, a GPU surfaceoptional, and absent where the platform has none

Binding and weaving

A model is a class with @Bind fields and @Action methods. Two mechanisms make an assignment observable, and they are interchangeable:

On the JVMIn a native image
mechanismreflection over the annotations at run timethe compiled class rewritten at build time
build stepnonethe weaver, one Gradle plugin or one Maven execution
a change notifiesat the next sweepinside the assignment

The same model, the same paths and the same refusals both ways (ADR-0155). Model weaving explains the mechanism and Native image what an image needs.

The modules

ModuleArtifactWhat it holds
:commongoldberry-commonlogging and the start-up timeline, the lowest module
:nativesgoldberry-natives and four classifier jarsthe FFM bindings and libgoldberry
:coregoldberry-corethe engines and the contracts: the three trees, style, layout, text, icons, paint, the backend SPI
:widgetsgoldberry-widgetsthe widget catalogue, charts included
:htmlgoldberry-htmloptional: Markdown and HTML as widgets
:emojigoldberry-emojioptional: the Noto Color Emoji face
:mediagoldberry-media and ffmpeg-<target> classifiersoptional: audio and video
:gpugoldberry-gpuoptional: canvas3d and GPU composition
:toolkitgoldberrythe umbrella an application depends on
:bomgoldberry-bomthe version table

:assets, :weaver and :example are build-time tools and the showcase. They are not published. The module graph is enforced by JPMS and the modules :common ← :natives ← :core ← :widgets are the spine (ADR-0007, ADR-0174). Repository layout has the packages.