lux is a GPU-accelerated UI framework for Go built on the Elm architecture. It combines a deterministic, single-threaded app loop with a modern rendering stack (wgpu/Vulkan/Metal/D3D12) and first-class support for accessibility, animations, and embedded/bare-metal targets.
go get github.com/timzifer/lux
Requires Go 1.25+.
- Elm architecture — pure
update(model, msg) → modelandview(model) → Element; no data races possible - GPU rendering — wgpu (Vulkan / Metal / D3D12 / WebGPU) with OpenGL 3.3 fallback
- CSS-compatible layout — Flexbox, CSS Grid, and HTML Table algorithms
- Animation system — deterministic, frame-driven
Anim[T]and spring physics; no goroutines - Design token theming —
LuxDark/LuxLightbuilt in; fully customisable - Rich widget catalogue — 20+ widgets (buttons, forms, navigation, data, menus, dialogs)
- Six platform backends — GLFW · Win32 · Cocoa · X11 · Wayland · DRM/KMS
- Accessibility — Windows UIA · macOS NSAccessibility · Linux AT-SPI2 (pure-Go D-Bus)
- i18n / RTL — BCP 47 locale propagation, Unicode BiDi & line-breaking, grapheme-aware cursor
package main
import (
"fmt"
"log"
"github.com/timzifer/lux/app"
"github.com/timzifer/lux/theme"
"github.com/timzifer/lux/ui"
"github.com/timzifer/lux/ui/button"
"github.com/timzifer/lux/ui/display"
"github.com/timzifer/lux/ui/layout"
)
// 1. Define your model.
type Model struct{ Count int }
// 2. Define your messages.
type IncrMsg struct{}
type DecrMsg struct{}
// 3. Pure update function — no side effects, no locks.
func update(m Model, msg app.Msg) Model {
switch msg.(type) {
case IncrMsg:
m.Count++
case DecrMsg:
m.Count--
}
return m
}
// 4. Pure view function — returns an Element tree.
func view(m Model) ui.Element {
return layout.Column(
display.Text(fmt.Sprintf("Count: %d", m.Count)),
layout.Row(
button.Text("-", func() { app.Send(DecrMsg{}) }),
button.Text("+", func() { app.Send(IncrMsg{}) }),
),
)
}
func main() {
if err := app.Run(Model{}, update, view,
app.WithTheme(theme.Default),
app.WithTitle("Counter"),
); err != nil {
log.Fatal(err)
}
}Run it:
go run ./examples/counter/
| Document | Description |
|---|---|
| Getting Started | Installation, prerequisites, annotated walkthrough |
| Elm Architecture | Model / Update / View / Cmd in depth |
| Architecture | Package map, rendering pipeline, app loop internals |
| Widget Catalogue | All widgets with API reference |
| Layout | Flexbox, CSS Grid, Table, Box, Stack, RTL |
| Theming | Design tokens, built-in themes, custom themes |
| Animation | Anim[T], spring physics, easing, AnimGroup/AnimSeq |
| Drawing API | draw.Canvas reference |
| Input & Events | Keyboard, mouse, touch, IME, shortcuts |
| Testing | Golden-file scene tests with uitest |
| Platform Backends | Backend selection and configuration |
| Accessibility | AccessTree, UIA, AT-SPI2, NSAccessibility |
| Advanced | |
| Custom Widgets | Implementing the Widget interface |
| State Persistence | Save/restore app state across restarts |
| RFC Index | Internal design documents |
go run ./examples/counter/ # simple counter with theme toggle
go run ./examples/kitchen-sink/ # comprehensive widget showcase
go run ./examples/fenster/ # window management| Platform | Backend | GPU | Notes |
|---|---|---|---|
| Windows 10+ | Win32 native / GLFW | Vulkan · D3D12 | |
| macOS 11+ | Cocoa / GLFW | Metal | |
| Linux (X11) | X11 / GLFW | Vulkan · OpenGL | |
| Linux (Wayland) | Wayland / GLFW | Vulkan · OpenGL | |
| Embedded / bare-metal | DRM/KMS | Vulkan · OpenGL | Raspberry Pi, industrial HMI |
┌─────────────────────────────────────────────┐
│ app package │ ← Elm loop, messages, commands
│ Run(model, update, view, opts...) │
└──────────────┬──────────────────────────────┘
│ Element tree
┌──────────────▼──────────────────────────────┐
│ ui package │ ← Widget system, layout, focus,
│ Widget → Render → reconcile → layout │ gestures, accessibility tree
└──────────────┬──────────────────────────────┘
│ draw.Canvas commands
┌──────────────▼──────────────────────────────┐
│ internal/render │ ← Scene graph, batching,
│ internal/gpu (wgpu) │ GPU upload, wgpu backend
└──────────────┬──────────────────────────────┘
│ native window / surface
┌──────────────▼──────────────────────────────┐
│ platform package │ ← GLFW · Win32 · Cocoa ·
│ Init · Run · Events · Clipboard │ X11 · Wayland · DRM/KMS
└─────────────────────────────────────────────┘
Design decisions are captured in the RFC documents.
Start there before opening a pull request for a new subsystem.
See CONTRIBUTING.md for build, test, and PR
conventions, and SECURITY.md for reporting
vulnerabilities.
lux uses a dual-license model:
- Noncommercial use (personal projects, hobbyists, research, education, nonprofits): free of charge under the PolyForm Noncommercial License 1.0.0.
- Commercial use requires a paid commercial license. See
LICENSING.mdfor details and how to get in touch.
Third-party components bundled under vendor_gogpu_wgpu/ retain
their own licenses; see NOTICE for attribution details.