GitHub - go-gui-org/go-gui: Cross-platform GUI framework for Go — no virtual DOM, no diffing, just fast, composable UI.

GitHub

4 min read Original article ↗

Go version License CI Ask DeepWiki Wiki

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.


https://go-gui.com

Documentation

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

Showcase contains the framework documentation. Every widget demo has a button in the upper-right corner that displays documentation about the widget.

Sibling projects:

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 notListBox, Table and Tree virtualize rows they own; VirtualList handles rows the app builds, of heights only the layout engine knows, and Window.ScrollToIndex addresses 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 Snapshotter on your state type and set DebugTimeTravel: true
  • Headless testing — all layout and widget logic runs without a display
  • Headless renderinggui/backend/soft rasterizes 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

gallery


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

  1. Install Go 1.26+ (a C toolchain too if developing on macOS, see Installation).
  2. Clone the repo.
  3. Run tests and lint:
go test ./...
go vet ./...
golangci-lint run ./...
  1. Open a pull request with a clear description of the change.

Digital Rain Screenshot

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.

License

MIT