What if building a desktop interface could feel like writing the rest of your Go application?
I'd like to introduce dxui, an MIT-licensed framework for building declarative desktop UIs in Go for Windows, macOS, and Linux.
You compose your interface with Go functions, typed props, and callbacks. Your application owns its state, and dxui updates the interface when that state changes. Both the framework and application builds support CGO_ENABLED=0.
A small footprint, with rendering on demand
dxui focuses on small binaries and low memory usage, making it worth exploring for desktop utilities and tools where resource use matters. The actual footprint depends on your platform, build configuration, assets, and application complexity.
Its rendering loop is event- and deadline-driven: it waits when idle and renders when needed. A window sitting open doesn't need to redraw continuously.
Try it before writing any code
You'll need Go 1.25 or newer and a native desktop environment.
Clone the repository and launch the component catalog:
git clone https://github.com/dxui-org/dxui.git
cd dxui
go run ./examples/components
The catalog lets you explore the controls, edit their properties, and switch between light and dark themes.
For a smaller application, try the calculator or login form:
go run ./examples/calc
go run ./examples/login
Build your first interface
Here's a small greeting form to show what the API looks like. It has a text input, a greeting that updates as you type, and a close button.
Start in a new directory:
mkdir dxui-greeting
cd dxui-greeting
go mod init example.com/dxui-greeting
go get github.com/dxui-org/dxui
Create main.go:
package main
import (
"log"
"github.com/dxui-org/dxui"
)
func main() {
app := dxui.NewApp(dxui.AppOptions{
Title: "Hello dxui", Width: 480, Height: 240,
})
name := ""
root := func() dxui.View {
return dxui.Box(dxui.BoxProps{
Style: dxui.Style{Padding: dxui.Padding(24)},
Gap: 12,
},
dxui.Label("What is your name?"),
dxui.Input(dxui.InputProps{
Key: "name", Value: name, Placeholder: "Your name",
OnChange: dxui.Assign(&name),
}),
dxui.Label("Hello, " + name + "!"),
dxui.TextButton(dxui.ButtonProps{OnPress: app.Close}, "Close"),
)
}
if err := app.Run(root); err != nil {
log.Fatal(err)
}
}
Then run it:
go run .
The name variable is ordinary Go state. The input's OnChange callback updates it through dxui.Assign(&name). dxui then rebuilds the view description and reconciles it with its internal retained tree, updating the greeting.
The root function describes the interface for the current state. As your UI grows, you can move parts of that description into separate Go functions.
For work that runs in background goroutines, use App.Update to schedule state changes. Call App.Run directly from main; it blocks until the application closes.
Build without cgo
To explicitly disable cgo when building on macOS or Linux:
env CGO_ENABLED=0 go build .
In Windows PowerShell:
$env:CGO_ENABLED = "0"
go build .
This applies to the framework and your application build. Running the application still requires a desktop environment.
Beyond a greeting form
dxui includes controls for everyday desktop interfaces:
- Forms: inputs, text areas, selects, checkboxes, radio buttons, switches, and sliders.
- Navigation and overlays: tabs, menus, popovers, and tooltips.
- Layout and content: boxes, scrolling, text, images, and icons.
- Styling: typed theme tokens, runtime light/dark switching, rounded corners, shadows, and interaction states.
It also supports multiple windows and keyed virtual lists for fixed-height rows. The repository includes a 100,000-row virtual-list example you can explore:
go run ./examples/virtual_list
The current platform focus is desktop: Windows, macOS, and Linux. Android isn't currently supported.
Give it a try
If you've wanted to build a desktop tool in Go, I'd love to hear how dxui works for your use case.
Feedback on API ergonomics, text rendering, and input behavior across operating systems is especially useful. If you encounter an issue, please include your OS and architecture, Go version, and a small reproduction. On Linux, desktop/compositor and GPU/driver details can also help diagnose window or rendering problems.
What desktop tool would you build with Go, and which GUI features would it need?

Top comments (0)