Show HN: A Modern GUI Library for Ada: CSS Styling, XML UI, SDL3

Hacker News Top Tools

Summary

Adi2 is a modern GUI library for Ada that provides CSS styling, XML-based UI layouts, and rich content rendering on SDL3, with WebAssembly support and tooling features.

No content available
Original Article
View Cached Full Text

Cached at: 08/24/26, 04:49 PM

ovenpasta/adi2

Source: https://github.com/ovenpasta/adi2

Adi2

A modern GUI library for Ada.

Adi2 gives you a real widget toolkit with the niceties developers expect from a modern UI stack — CSS-like styling with live reload, declarative XML layouts, animations, SVG and Lottie graphics, internationalization, and asset bundling — implemented natively in Ada on top of SDL3.

Status: in production use, but not yet a stable release — APIs may still change between versions.


Why Adi2?

  • Style your UI like the web. Selectors, pseudo-classes, parts, transitions, gradients, box shadows — all in a familiar .css syntax. Edit the file, save, see the change. No recompile during development. Prefer pure Ada? CSS rules are just plain Ada aggregates of Style_Rules — write them by hand with no extra ceremony (see the snippet below).
  • Describe UIs declaratively — or don’t. Write <button>, <grid>, <text-editor> in XML and let the toolchain emit clean Ada packages, or construct the same widget tree directly in Ada with handle-based builders. Both paths target the exact same API; the XML generator is a convenience, not a requirement.
  • Render rich content. A built-in lightweight HTML view widget renders documentation-style markup with cascading styles. Raster images through SDL3_image, SVG through the bundled plutosvg, Lottie animations through bundled rlottie.
  • Ship a single binary. Bundle every CSS file, font, image, translation, and SVG sprite into your executable. No filesystem dependencies at runtime.
  • Speak the user’s language. Gettext-compatible i18n with plural forms, automatic locale detection, and .po → Ada compilation.
  • Animate without boilerplate. CSS transitions on color, background-color, border-color, border-width, border-radius, padding, margin, opacity, box-shadow and font-size — the framework handles interpolation and timing.
  • HiDPI-ready units. dp/dip for layout, rem for typography, pix when you mean one renderer pixel exactly, and px — which follows the display scale or not, depending on Set_Px_Maps_To_Dip. See docs/css_styling.md.
  • Built for tooling and automation. A development-only MCP bridge lets editors and AI assistants screenshot the running app, walk the widget tree, and drive it — clicking buttons, typing into inputs, moving focus, reading performance counters. Great for end-to-end tests written by your AI of choice.
  • Runs in the browser. The examples compile to WebAssembly with GNAT-LLVM and Emscripten — try them live, or see wasm/ for the build.

What that costs to ship

A release build links statically into a single executable under 10 MB — the widget toolkit, the CSS engine, SVG and Lottie rendering, all of it. Whatever assets you bundle add their own weight to that.

It draws through SDL’s renderer, which binds to whatever the host offers: Direct3D on Windows, Metal on macOS, Vulkan or OpenGL where they exist, software as the floor. Windows XP takes Direct3D 9 and a current Mac takes Metal, from the same source.

Adi2QtFlutterElectron
Ship size<10 MB, one file~15–30 MB static; otherwise a Qt runtime alongside~20 MB+, engine plus a data directory~100 MB+, bundling Chromium and Node
Runtimeself-containedQt libraries and pluginsFlutter engine; GTK3 on LinuxChromium and Node
GraphicsSDL renderer, software fallback includedGPU or raster backendsSkia or Impeller, GPU expectedGPU stack and compositor
PortabilityWindows XP+, macOS, Linux, WebAssemblyWindows 10+, macOS, Linux, mobile, embeddedWindows 10+, macOS, Linux, mobile, webWindows 10+, macOS, Linux
LanguageAdaC++DartJavaScript
Memory safetychecked, deterministic reclamationmanualgarbage-collectedgarbage-collected
StylingCSSQSSDart widget codeCSS

Sizes are for a minimal application; yours grows with your own code and assets. Each of the others buys its size with a large ecosystem and years of production use — the trade Adi2 offers is a single file you can hand to someone, on hardware the others have moved past.


Screenshots

hello_example hello_example

material_demo material_demo

html_view_example html_view_example

rlottie_example rlottie_example

assets_example assets_example

Full gallery of every example: docs/gallery.md. Or run them yourself, in the browser: live demos.


A taste

Declarative path — XML + CSS

/* examples/css/hello_example.css */
.primary {
  background-color: rgb(37, 99, 235);
  border-radius: 8px;
  padding: 10px 16px;
  transition: background-color 150ms ease-out;
}
.primary:hover  { background-color: rgb(29, 78, 216); }
.primary::label { color: white; font-size: 14px; font-weight: 500; }
<!-- examples/xml/hello_example.xml -->
<adi>
  <link rel="stylesheet" href="examples/css/hello_example.css"/>
  <callback name="On_Hello_Click" type="Adi.Widget.Button.Click_Callback"/>
  <window title="Hello, Adi" width="320" height="180">
    <box class="root">
      <label text="Welcome to Adi" class="welcome"/>
      <button text="Click me" class="primary" on-clicked="On_Hello_Click"/>
    </box>
  </window>
</adi>

The toolchain emits a typed Ada package you instantiate from your main — see examples/hello_example.adb for the full ~25-line program.

Same thing, written by hand in Ada

The CSS rule above is just an aggregate. The XML widget tree is just a few constructor calls. Both paths land on the same API — see examples/hello_raw_example.adb for the full equivalent program. The shape of the styling code is:

function Style return Style_Builder renames Adi.Widget_Styles.Create;

--  Equivalent of .primary base + :hover from hello_example.css
Primary_Base : constant Style_Rules :=
  (Background_Color => Set_Bg (RGB (37, 99, 235)),
   Border_Radius    => Set (Radius (Px (8.0))),
   Padding          => Set (CSS_Box (Px (10.0), Px (16.0))),
   Transition       => Set ((Duration   => 0.15,
                             Easing     => Ease_Out,
                             Properties => Props (Prop_Background_Color))),
   others           => <>);

Primary_Hover : constant Style_Rules :=
  (Background_Color => Set_Bg (RGB (29, 78, 216)),
   others           => <>);

--  Wire base + hover to the button's Main_Part
Set_Part_Style (Widget_Handle'(+Btn), Main_Part,
  Style.Base (Primary_Base).On_Hover (Primary_Hover).Build);

Build and run either flavour:

tools/build_examples.sh hello_example hello_raw_example
./examples/bin/hello_example       # XML + CSS pipeline
./examples/bin/hello_raw_example   # pure hand-written Ada

Quick start

# Build the library
alr build -- -j0

# Build and run the test suite
tools/run_tests.sh

# Build all example programs
tools/build_examples.sh

# ...or just one
tools/build_examples.sh stack_example

# Try a demo
./examples/bin/material_demo
./examples/bin/html_view_example

To use Adi2 from your own project, with "adi.gpr" — SDL linker options come with it. The library’s public specs use Ada 2022 constructs, so units that with Adi.* packages need pragma Ada_2022; or -gnat2022.

Starting your own project? docs/getting_started.md walks from an empty directory to a working window, in XML/CSS and again in plain Ada.

Full build instructions, including building without Alire, in docs/build.md and docs/gprbuild_without_alire.md.


Roadmap

CSS.

  • Broader CSS surface — more standard properties, selectors and values.

HTML view.

  • Tablestable, tr, td/th, column widths, spanning.
  • Flex and griddisplay: flex and display: grid inside the document.

Widgets and themes.

  • More widgets — tree view, data grid, menu bar, progress and busy indicators, tooltips, split panes, date and colour pickers.
  • Ready-made themes — Material, Fluent, Adwaita and macOS, each in light and dark.

Text and reach.

  • Right-to-left and bidirectional textdirection and bidi reordering.
  • Accessibility — semantic roles, names and states to screen readers over AT-SPI, UI Automation and NSAccessibility.

Portability.

  • Pluggable backends — an abstraction layer that lets Win32/Direct2D, Cocoa, GLFW, raylib or Skia take the place of SDL3 (design notes).
  • Embedded devices

Authoring and tooling.

  • Visual designer — RAD IDE like experience, edit both the UI XML and CSS.
  • Scripting with HAC — embed the HAC Ada compiler for reloadable application logic.
  • Live reload for XML UIs — XML widget trees hot-reload as CSS already does.
  • Better generated docs — browsable API documentation with gnatdoc.

Correctness and API.

  • Better callbacks — a callback that fails leaves the app running, callbacks that fire once, and background work that talks to the UI safely (design notes).
  • ContractsPre/Post/Type_Invariant and SPARK-mode subsets.
  • C API — a stable C-callable interface for non-Ada callers.

Have an idea? Open an issue (see CONTRIBUTING.md for the policy).


Supported platforms

Tested on GNU/Linux, Windows (XP, 7, 8, 10, 11, via MinGW), macOS, and WebAssembly (Emscripten). Anywhere else GNAT and SDL3 build should follow — the BSDs among them.

Rendering goes through the SDL renderer abstraction, so it takes hardware acceleration where the machine offers it and falls back to software where it does not. That is what puts the same binary on Windows XP and on a current desktop.


Questions

Why “Adi2”? And why is the Ada package still Adi.*? “adi” is too common a word for search engines — Adi2 is findable. The in-code namespace stays Adi.* because with Adi.Widget.Button; reads better than Adi2.Widget.Button and renaming it would churn every source file for zero functional gain. Project = Adi2, package = Adi.


Talk

A Native, Portable GUI Framework for Ada — 3rd Ada Developers Workshop, AEiC 2026, 13 June 2026. Building an Adi2 application, and driving the running UI from an LLM through the MCP bridge.

Part 1 · Part 2


Go deeper

TopicDoc
Your first Adi2 applicationdocs/getting_started.md
High-level architecture and core componentsdocs/architecture.md
CSS styling — selectors, properties, runtime API, codegendocs/css_styling.md
Declarative XML UIs and the widget grammardocs/xml_ui_system.md
HTML view widget specificationdocs/html_view_spec.md
Static asset bundling (single-binary deployments)docs/static_assets.md
Internationalization, plurals, .po compilationdocs/i18n.md
Settings store with JSON backenddocs/settings.md
OS integration — dialogs, clipboard, pathsdocs/os_integration.md
Signals and deferred dispatchdocs/signals.md
Antialiased rendering primitivesdocs/rendering_aa.md
MCP runtime introspection and interactiondocs/mcp.md
Handle ownership modeldocs/handle_ownership.md
Coding conventionsdocs/coding_conventions.md
Adding a CSS property / example / testdocs/adding_css_property.md, docs/adding_example.md, docs/adding_test.md

Contributing

Issues and pull requests welcome.

For anything beyond a small fix, please open an issue first so the approach can be discussed before you invest time in it. Match the existing code style (docs/coding_conventions.md), keep the tests green, and add tests for new behaviour.

Unless you explicitly state otherwise, contributions you submit are understood to be under the Apache-2.0 license, as per its Section 5 — no CLA to sign. Full details in CONTRIBUTING.md.


Sponsoring

Adi2 is independently developed and maintained. Sponsorship funds ongoing maintenance, cross-platform testing, documentation, and work on the public roadmap.

Organisations interested in supporting the project, or in funding a specific feature, port, or integration: [email protected].

Sponsorship supports the project as a whole. Guaranteed response times or delivery commitments require a separate commercial agreement.


License

Apache-2.0. See LICENSE.

Vendored third-party code under vendor/ retains its original licenses, listed in each tree’s own license files. Most are permissive — MIT, Apache-2.0, BSD-style, OFL. vendor/rlottie/src/vector/vinterpolator.cpp is MPL-2.0, a file-level copyleft rather than a permissive licence; its text ships as vendor/rlottie/licenses/COPYING.MPL.

Example assets under examples/assets/ are demonstration content rather than part of the library; those with known third-party terms are attributed in examples/assets/NOTICE.md.


Contact

Adi2 is written by Aldo Nicolas Bruno. Report bugs and propose features through the issue tracker. For private enquiries, sponsored development, or commercial support: [email protected].

Similar Articles

Show HN: An ASCII 3D Rendering Engine

Hacker News Top

GlyphCSS is a JavaScript library that renders textured 3D meshes in the DOM using ASCII characters, supporting various 3D formats and integrating with vanilla JS, React, and Vue.

Show HN: A CSS 3D Engine (no WebGL)

Hacker News Top

PolyCSS is a CSS polygon mesh library that renders 3D models as real HTML elements using CSS matrix3d, supporting OBJ/MTL, GLB, and VOX formats with React, Vue, or vanilla JS.

CSS-DOS — A computer made of CSS

Lobsters Hottest

A creative project that builds a DOS-like computer interface entirely with CSS, showcasing the power of modern frontend styling.

Gsxui – Shadcn-style components for Go

Hacker News Top

Gsxui is a shadcn-style component set for Go, enabling copy-in, type-checked, server-rendered UI components styled with Tailwind. It provides a CLI to initialize and add components.