NeferGUI
A pure-Go GUI renderer for Linux: build your view from the current model, style it with CSS, and draw it with Vulkan into DMA-BUF buffers. Controls return events during the view call. No cgo required.
NeferGUI imports no Wayland library. Your application owns the Wayland client (connection, surface, linux-dmabuf feedback, buffer import, seat events) and drives a Renderer; github.com/bnema/neferclient is a client toolkit built for this. The two do not import each other: the application copies plain fields between them.
[!WARNING]
Early development. No release yet. Expect bugs and breaking changes. Platform accessibility is not connected.
A small example
The view is plain Go. The model type is yours.
type Model struct{ Count int }
view := func(f *nefergui.Frame, m *Model) {
root := f.Root().Column()
root.Text("Hello, Wayland!")
if root.Button("Count", nefergui.Key("count")).Activated() {
m.Count++
}
root.Text(fmt.Sprintf("Clicked %d times", m.Count))
}
The client loop, on one owner goroutine:
r, err := nefergui.NewRenderer(nefergui.RendererConfig{MainDevice: dev, Formats: formats})
r.Resize(320, 200, 1) // on configure and scale changes
r.Input(&nefergui.Input{...}) // for each pointer, key and focus event
var out nefergui.Output
if ok, err := r.Render(&out, &model, view); ok && err == nil {
// import out.Planes as a wl_buffer when out.NewBuffer, attach with the
// acquire/release points, commit
}
r.Released(buffer) // when out.ReleaseFD becomes readable
RendererConfig.Styles loads your own CSS; default styles work without it. See ExampleRenderer and runtime for the full contract.
Demo
examples/demo is a document workspace (toolbar, document list, text editor, properties pane, light and dark themes) in a Wayland window, using neferclient as the client. It lives in its own module, so NeferGUI does not depend on neferclient, and it always builds against the NeferGUI code in this checkout:
cd examples && go run ./demo
Requirements
Go 1.27, libvulkan.so.1 and usable fonts. The GPU must export DMA-BUF and support DRM syncobj timelines (kernel 6.6 or later for eventfd waits). The compositor, reached through your Wayland client, must offer linux-dmabuf and linux-drm-syncobj; fractional scaling also needs viewporter. No X11 or software-rendering fallback.
go get github.com/bnema/nefergui
Documentation
License
GNU GPL v3. Third-party code and test fonts retain their own licenses and attribution.
source
1# NeferGUI
2
3A pure-Go GUI renderer for Linux: build your view from the current model, style it with CSS, and draw it with Vulkan into DMA-BUF buffers. Controls return events during the view call. No cgo required.
4
5NeferGUI imports no Wayland library. Your application owns the Wayland client (connection, surface, linux-dmabuf feedback, buffer import, seat events) and drives a `Renderer`; [github.com/bnema/neferclient](https://github.com/bnema/neferclient) is a client toolkit built for this. The two do not import each other: the application copies plain fields between them.
6
7> [!WARNING]
8> **Early development.** No release yet. Expect bugs and breaking changes. Platform accessibility is not connected.
9
10## A small example
11
12The view is plain Go. The model type is yours.
13
14```go
15type Model struct{ Count int }
16
17view := func(f *nefergui.Frame, m *Model) {
18 root := f.Root().Column()
19 root.Text("Hello, Wayland!")
20 if root.Button("Count", nefergui.Key("count")).Activated() {
21 m.Count++
22 }
23 root.Text(fmt.Sprintf("Clicked %d times", m.Count))
24}
25```
26
27The client loop, on one owner goroutine:
28
29```go
30r, err := nefergui.NewRenderer(nefergui.RendererConfig{MainDevice: dev, Formats: formats})
31r.Resize(320, 200, 1) // on configure and scale changes
32r.Input(&nefergui.Input{...}) // for each pointer, key and focus event
33
34var out nefergui.Output
35if ok, err := r.Render(&out, &model, view); ok && err == nil {
36 // import out.Planes as a wl_buffer when out.NewBuffer, attach with the
37 // acquire/release points, commit
38}
39r.Released(buffer) // when out.ReleaseFD becomes readable
40```
41
42`RendererConfig.Styles` loads your own CSS; default styles work without it. See `ExampleRenderer` and [runtime](docs/runtime.md) for the full contract.
43
44## Demo
45
46[`examples/demo`](examples/demo) is a document workspace (toolbar, document list, text editor, properties pane, light and dark themes) in a Wayland window, using neferclient as the client. It lives in its own module, so NeferGUI does not depend on neferclient, and it always builds against the NeferGUI code in this checkout:
47
48```sh
49cd examples && go run ./demo
50```
51
52## Requirements
53
54Go 1.27, `libvulkan.so.1` and usable fonts. The GPU must export DMA-BUF and support DRM syncobj timelines (kernel 6.6 or later for eventfd waits). The compositor, reached through your Wayland client, must offer linux-dmabuf and linux-drm-syncobj; fractional scaling also needs viewporter. No X11 or software-rendering fallback.
55
56```sh
57go get github.com/bnema/nefergui
58```
59
60## Documentation
61
62- [Controls](docs/controls.md) and [layout](docs/layout.md)
63- [CSS properties and limitations](docs/css.md)
64- [Runtime requirements and behavior](docs/runtime.md) and [troubleshooting](docs/troubleshooting.md)
65- [Performance](docs/performance.md)
66- [Architecture decisions](docs/adr)
67
68## License
69
70[GNU GPL v3](LICENSE). Third-party code and test fonts retain their own licenses and attribution.