Gio: immediate mode Go user interfaces across nine platforms, tracked on sourcehut
Mirror of the Gio main repository (https://git.sr.ht/~eliasnaur/gio)
At a glance
- What is it?
- The GitHub repository is a mirror. Development, issues and patches live on sourcehut, the build runs on builds.sr.ht, and the module itself is a single gioui.org import path.
- Who is it for?
- Gio is a credible choice for a Go program that needs a native user interface on more than one operating system, particularly when the targets include mobile. The immediate mode model removes the widget tree and the layout pass from your code, the package split across `layout/`, `widget/`, `text/` and `gesture/` maps closely onto the problems you actually have, and the module keeps its dependency list short.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.
Editorial analysis
This repository is a mirror, and that changes where you file things
The repository description says it plainly: this is a mirror of the Gio main repository at git.sr.ht/~eliasnaur/gio. The README calls the same repository an official GitHub mirror, and the only topics on the GitHub repository are `gio` and `mirror`.
So the practical consequence is that the workflow you would expect from a GitHub project does not apply. Bugs and TODOs go through the issue tracker at todo.sr.ht/~eliasnaur/gio, or by email to the same address. General discussion happens on a mailing list at lists.sr.ht/~eliasnaur/gio. Patches are posted to a second mailing list, gio-patches, and the README notes that no sourcehut account is required and that you can post without being subscribed.
Two details in the tree confirm the build is hosted on sourcehut as well. There is a `.builds/` directory holding the continuous integration definition, and the README's status badge points at builds.sr.ht/~eliasnaur/gio rather than at GitHub Actions.
There are no releases published on this repository. If you are pinning a version, you are reading tags from the sourcehut repository, not from the GitHub releases page. The last push to the mirror was on 2026-09-28, so the mirror itself is being kept current rather than abandoned on an old snapshot.
Immediate mode, and what that actually changes in your code
The README's first line describes the scope: immediate mode GUI programs in Go for Android, iOS, macOS, Linux, FreeBSD, OpenBSD, Windows, and WebAssembly, with WebAssembly marked experimental.
Immediate mode is the design decision that defines everything else. In a retained mode toolkit you build a tree of widget objects that own their state, and the framework runs a layout pass to place them. In an immediate mode toolkit you write a function that describes what the interface looks like right now, given the current state, and that function runs again every frame. There is no widget tree to keep in sync and no layout pass to reason about, at the cost of re-executing your drawing code continuously.
The `unit/` package in the tree is the giveaway that this is a deliberate, quantitative design. Gio does not measure layout in pixels. It works in device-independent units with an explicit scale factor, so the same layout code produces the same physical size on a phone and on a desktop. For an application that has to look right on both, that is not a convenience, it is most of the problem.
The rest of the tree maps onto the problems you will hit in order. `app/` is window creation and the event loop. `op/` is the operation list that immediate mode code emits. `layout/` covers the stack and direction containers. `widget/` holds ready-made widgets including buttons, lists and material-style components. `text/` handles shaping and layout. `gesture/` deals with input. `font/` covers font loading and OpenType. `gpu/` is the shader and rendering layer, `io/` handles input devices, and `f32/` holds fixed point numbers for layout arithmetic, since floating point and integer layout maths do not mix cleanly.
A short dependency list, and one module path for everything
The module manifest is compact and worth reading as a statement about the project's priorities. The module is `gioui.org`, so every import in a Gio program uses that single host, and it requires Go 1.24.0.
module gioui.org
go 1.24.0The direct dependencies are few and each has an obvious job. `eliasnaur.com/font` is the author's own font handling library. `gioui.org/shader` at version 1.0.9 is the shader compiler, split into its own module because it changes on a different schedule from the UI code. `github.com/go-text/typesetting` does text shaping and font layout. From the Go ecosystem there is `golang.org/x/exp/shiny` for windowing and input, plus `golang.org/x/image`, `golang.org/x/sys`, `golang.org/x/text` and `golang.org/x/net`, and `github.com/godbus/dbus/v5` for desktop notifications on Linux.
That `shiny` dependency is the important one to understand. Gio does not implement its own windowing. On desktop platforms it sits on Go's experimental windowing package, which is why Gio works on Linux, macOS, Windows and three BSDs without Gio carrying nine platform backends itself. It also explains why the dependency is marked experimental and pinned to a specific pseudo-version.
The separate `gioui.org/shader` module is worth noting separately because it explains the `gpu/` directory. Shader compilation is not part of the UI code, and its dependency version moves independently, so pinning it separately is what lets the UI library move at one pace and the graphics layer at another.
Versioning rules you need to read before pinning anything
The README's Tags section is short and unusually important for anyone adopting this library.
The first statement is that pre-1.0 tags are provided for reference only, do not designate releases with ongoing support, and that bugfixes will not be backported to older tags. That is a materially different support policy from most Go libraries, where pinning an old version and applying a patch is the normal maintenance path.
The second statement explains the versioning convention. Tags follow semantic versioning, and because the major version is zero, breaking API or behaviour changes increment the minor version component while non-breaking changes increment the patch component. So a zero-major library in this scheme treats minor releases as the breaking ones. Moving from 0.15 to 0.16 is the upgrade that can break your code, and 0.15.2 to 0.15.3 is the one that should not.
Combine those two and the adoption rule is clear. Pin to an exact tag, read the diff before bumping across a minor version, and do not expect a backported fix on the tag you already pinned. Since there are no releases on the GitHub mirror, the tags to read are on sourcehut.
The repository also ships `flake.nix` and `flake.lock`, so a Nix-based build has a reproducible entry point, which is a small convenience that says something about the audience.
Comparing Gio with the other Go GUI options
Go has more than one credible GUI toolkit now, and the choice comes down to what you are optimising for. The main alternatives people compare Gio against are Fyne, which is also pure Go and also targets mobile, and the official Go project bindings, which wrap a native toolkit on each platform.
The difference in approach between Gio and a native-binding toolkit is the same difference as between Gio and Fyne, one level down. Bindings give you platform-native widgets that look like the rest of the operating system, at the cost of your interface looking different on macOS than on Windows, and of behaviour that is only partly in your control. Gio draws everything itself through its own renderer, so your interface looks identical everywhere and every pixel is under your control, at the cost of not inheriting native behaviour for free.
Where Fyne differs from Gio is in layout units and in the toolkit's overall shape. Gio's device-independent unit system is built for exactly the multi-platform case, while Fyne takes a different approach to the same problem. Both are pure Go and both reach Android and iOS.
The honest limitation to weigh against any of them is the WebAssembly story. Gio lists WebAssembly among its targets but marks it experimental. If a browser target is a hard requirement rather than a nice-to-have, that is the part of Gio's support matrix to test first, before anything else.
Where the documentation actually lives, and what the mirror is good for
The README is short by design, and its instruction for everything else is a single sentence: go to gioui.org. Installation instructions, examples and documentation are all there, and there is a contribution guide at gioui.org/doc/contribute.
That split is sensible for a project hosted on sourcehut but it means the GitHub repository is close to useless as a source of documentation. It has one README, no releases, two topics, and a manifest. What it does offer is a stable, familiar URL, a commit history that is kept current, and somewhere to point a `go get` that resolves through the module proxy regardless of where the code lives.
The licence deserves a note rather than a claim. The metadata attached to this repository carries no licence assertion, which is not the same as the project having no licence. There is a `LICENSE` file at the root of the tree, and that file is what governs. This is a normal artefact of mirroring a repository whose licence lives upstream, but it is exactly the sort of thing to check before shipping a Gio application inside a product with a compliance review.
The 19 open issues on this repository should be read with the mirror in mind. An issue filed here does not reach the tracker where the project actually works, so the count reflects GitHub users filing in the wrong place as much as it reflects anything about the codebase. The todo.sr.ht tracker is the number that would tell you something.
Editorial conclusion
Gio is a credible choice for a Go program that needs a native user interface on more than one operating system, particularly when the targets include mobile. The immediate mode model removes the widget tree and the layout pass from your code, the package split across `layout/`, `widget/`, `text/` and `gesture/` maps closely onto the problems you actually have, and the module keeps its dependency list short. Two things to settle first. This GitHub repository is a mirror with no releases attached, so pin a version tag from sourcehut rather than tracking `main` from here. And WebAssembly is marked experimental in the README, so a web target is a different risk profile from the desktop and mobile ones. Read the documentation at gioui.org, then start from the `app/` package, because that is where window creation and the event loop live.
Frequently asked questions
What platforms does Gio support?
The README lists Android, iOS, macOS, Linux, FreeBSD, OpenBSD and Windows for immediate mode GUI programs in Go, and WebAssembly as experimental. Desktop windowing is provided by the `golang.org/x/exp/shiny` dependency rather than by Gio itself, which is why the same library covers that many systems.
Where do I file bugs and send patches for Gio?
The GitHub repository at gioui/gio is a mirror of the main repository on sourcehut. Bugs and TODOs go to the issue tracker at todo.sr.ht/~eliasnaur/gio, discussion happens on the mailing list at lists.sr.ht/~eliasnaur/gio, and patches are posted to lists.sr.ht/~eliasnaur/gio-patches. No sourcehut account is needed to post.
How does Gio version its releases?
Tags follow semantic versioning with a major version of zero, so breaking API or behaviour changes increment the minor component and non-breaking changes increment the patch component. The README also states that pre-1.0 tags are for reference only and that bugfixes will not be backported to older tags.
How is Gio different from Fyne for building a Go desktop app?
Both are pure Go and both target Android and iOS. The distinguishing detail in Gio is its `unit/` package, which measures layout in device-independent units with an explicit scale factor rather than in pixels, so one layout produces the same physical size across a phone and a desktop. Gio also ships WebAssembly support, though the README marks that target experimental.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/gioui-gio)