Cross-platform, hybrid immediate-mode GUI framework for Go — no virtual DOM, no diffing, just fast, composable UI.
package main import ( "fmt" "github.com/go-gui-org/go-gui/gui" "github.com/go-gui-org/go-gui/gui/backend" ) type App struct{ Clicks int } func main() { w := gui.SimpleWindow("Counter", 300, 150, &App{}, func(w *gui.Window) { w.UpdateView(mainView) }) backend.Run(w) } func mainView(w *gui.Window) gui.View { app := gui.State[App](w) return gui.Column(gui.ContainerCfg{ Content: []gui.View{ gui.Label(fmt.Sprintf("%d Clicks", app.Clicks), gui.TextStyle{}), gui.TextButton("counter", "Click Me", func(ctx gui.EventCtx) { gui.State[App](ctx.Window).Clicks++ }), }, }) }
gui.Label(text, style) — pass the zero TextStyle{} for the default theme
style. gui.TextButton(id, label, onClick) and gui.SimpleWindow are the same
thin forwards; the ID argument stays explicit because identity is
caller-owned.
Full control
Every convenience form forwards to the matching Cfg struct. Use it when you
need the knobs — fonts, colors, sizing, padding, events:
w := gui.NewWindow(gui.WindowCfg{ State: &App{}, Title: "Counter", Width: 300, Height: 150, OnInit: func(w *gui.Window) { w.UpdateView(mainView) }, }) gui.Button(gui.ButtonCfg{ ID: "counter", Content: []gui.View{gui.Text(gui.TextCfg{Text: "Click Me"})}, Padding: gui.NewPadding(8, 16, 8, 16), OnClick: func(ctx gui.EventCtx) { gui.State[App](ctx.Window).Clicks++ }, })
See examples/get_started/ for the full runnable
version and examples/web_demo/ for the browser build.
Guides: Debugging · Theming · Testing
Try It
| Platform | Download |
|---|---|
| Browser (WASM) | Open Showcase — zero install, instant evaluation |
| macOS | Go-Gui-Showcase-<version>.dmg |
| Linux | go-gui-showcase-<version>-linux-amd64.tar.gz |
| Windows | go-gui-showcase-<version>-windows-amd64.zip |
Showcase contains the framework documentation. Every widget demo has a button in the upper-right corner that displays documentation about the widget.
Sibling projects:
-
go-charts
Interactive chart widgets. https://github.com/go-gui-org/go-charts -
go-edit
Code editor widget. https://github.com/go-gui-org/go-edit -
go-kite
Desktop Bluesky client. https://github.com/go-gui-org/go-kite -
go-map
SMIL map widgets. https://github.com/go-gui-org/go-map -
go-term
Embeddable terminal emulator. https://github.com/go-gui-org/go-term -
go-glyph
Text rendering engine on steroids. https://github.com/go-gui-org/go-glyph
Why
GUI frameworks in Go target the browser and tie you to HTML/CSS and JavaScript. go-gui takes the opposite approach: write your UI in pure Go, render it with native GPU acceleration — no browser runtime, no JavaScript bridge, no DOM. Your data stays in Go structs; your UI stays in Go code.
The second thesis: a GUI toolkit should be an ecosystem of composable libraries, not a monolith. go-glyph handles text. go-charts handles data. go-edit handles code. Each library is usable on its own or together — all sharing the same rendering pipeline and event system.
Features
- 50+ widgets — buttons, inputs, sliders, tables, trees, tabs, menus, dialogs, toasts, DataGrid with virtualization (CSV/XLSX/PDF export), Markdown and RTF views, SVG rendering, and more
- Virtualized lists, uniform or not —
ListBox,TableandTreevirtualize rows they own;VirtualListhandles rows the app builds, of heights only the layout engine knows, andWindow.ScrollToIndexaddresses a row that does not exist yet - GPU-accelerated — Metal (macOS), OpenGL (Linux/Windows), WebGL/WASM (browser), Metal/UIKit (iOS)
- Animation subsystem — keyframe, spring, tween, hero transitions, color filters, box shadows, blur effects
- Touch gesture recognition — tap, double-tap, long-press, pan, swipe, pinch, rotate with automatic mouse-event synthesis
- Time-travel debugging — opt-in scrubber rewinds/replays app state
frame-by-frame; implement
Snapshotteron your state type and setDebugTimeTravel: true - Headless testing — all layout and widget logic runs without a display
- Headless rendering —
gui/backend/softrasterizes a frame to a PNG on the CPU, with real text metrics and no GPU, for CI screenshots and pixel-level regression tests - Cross-platform integration — native file dialogs, menus, notifications, print/PDF, system tray, IME, a11y, spell check
- go-glyph powered — professional text shaping, rendering, bidirectional layout
Installation
Requires Go 1.26+. A C toolchain (CGo) is needed only on macOS — the
Metal backend is Objective-C. Linux and Windows build fully cgo-free
(CGO_ENABLED=0 go build ./...). The desktop backends are native: Metal on
macOS, X11 + EGL on Linux, Win32 + WGL on Windows. Text shaping and
rasterization are pure Go via go-glyph.
go get github.com/go-gui-org/go-gui
See the Installation Guide for platform-specific instructions.
Contributing
- Install Go 1.26+ (a C toolchain too if developing on macOS, see Installation).
- Clone the repo.
- Run tests and lint:
go test ./...
go vet ./...
golangci-lint run ./...- Open a pull request with a clear description of the change.
Roadmap
Planning lives in GitHub Issues and the go-gui-org project board, not a checked-in roadmap file. Browse open issues for current and planned work.
Debugging
Set GOGUI_DEBUG=1 (or gui.Debug(true)) to audit every frame for duplicate
widget IDs and focusable widgets without IDs. gui.DebugCategories enables each
class of finding — duplicates, missing IDs, unconsumed events, listbox
virtualization — independently. See the
Debugging wiki page.


