Open-source project
david-vanderson/dvui avatar
david-vanderson/dvui

DVUI: an immediate mode Zig GUI that can sit on top of your game

Immediate Zig GUI for Apps and Games

1,707 stars149 forksZigNOASSERTION

At a glance

What is it?
DVUI is a Zig GUI toolkit whose distinguishing feature is not its widget set but its three integration modes, including an overlay mode that draws a debug HUD on an application you did not write. It targets Zig v0.17.0, supports multiple backends, and has gaps it documents rather than hides.
Who is it for?
Adopt DVUI if you are writing Zig and want to either own the main loop or drop a HUD onto an existing window without restructuring that application, because the standalone and ontop modes are unusual and useful, and because `zig build sdl3-app` gets you a running window you can edit in `./examples/app.zig`.
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 2 days ago.
What is it written in?
Mainly Zig, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Three integration modes, and the third is the unusual one

The README's example matrix is organised by integration mode rather than by backend, and that is the design decision to understand first.

As app means DVUI owns the main loop. The standalone mode means you own the main loop and DVUI renders inside it. On top means a debug HUD drawn over an application you did not write and did not instrument.

The third mode is what separates DVUI from ordinary toolkit choices. The feature list says DVUI is appropriate for a whole UI, using the `*-app` examples, or for debugging on top of an existing application, and the project description frames it as a toolkit for whole applications or debugging windows in existing apps and games. An immediate mode GUI with no retained widget tree is a good fit for this, because there is no state to serialise into someone else's window and nothing to reconstruct between frames.

The shipped examples make the modes concrete. `examples/app.zig` is the app-mode entry point. The standalone files are named `*-standalone.zig`, including `sdl-standalone.zig`, `dx11-standalone.zig`, `raylib-zig-standalone.zig`, `pugl-standalone.zig` and `docking-standalone.zig`. The overlay files are named `*-ontop.zig`, and there is also `examples/sdl-multi-win.zig`, `examples/frame-dump.zig` and `examples/devtools.zig`.

Other platform directories exist beyond the desktop matrix: `examples/android-example/` and `examples/ios-example/`.

One behavioural note in the feature list matters more than it looks. DVUI processes every input event and the README says this makes it suitable for low frame rate situations. A GUI that never misses an event is acceptable when the alternative is dropping input on a stalled frame.

The backend matrix, including the cells that say todo

The README publishes a full matrix of backend by mode, and it is more useful than a feature list because it shows exactly where the project is incomplete.

SDL3 has all three modes, and `zig build sdl3-app` is what the README recommends as a starting point, telling you to try changing `frame()` inside `./examples/app.zig`. SDL2 also has all three: `sdl2-app`, `sdl2-standalone`, `sdl2-ontop`.

Then the gaps. SDL3GPU, described as rendering via SDL GPU, has standalone and ontop examples but its app cell reads `todo`. GLFW has `glfw-app` and an OpenGL ontop example, but its standalone cell reads `todo`. pugl, which is OpenGL on pugl, has app and standalone but its ontop cell reads `none`. Web has `web-app` and `none` in the other two.

Raylib appears twice, once through the C API and once through the raylib-zig bindings, and both have all three modes. DX11 has all three. The wio backend, OpenGL on wio, has all three, and Vulkan on wio is reached by adding `-Drenderer=vulkan` to `wio-app`, `wio-standalone` or `wio-ontop`.

So the backend list in the feature overview is longer than the working combinations. That gap table is the most honest quality signal the project publishes, and it is worth more than any count of widgets.

Supporting pieces are listed too: TinyVG icons via `zig-lib-svg2tvg` and `zig-lib-icons`, raster images via `stb_image`, and fonts via FreeType or `stb_truetype`. Touch input covers selection draggables in text entries and pinch-zoom scaling. Native file dialogs come from `tinyfiledialogs`.

Building your first window with zig build

The entry point is a single command, and the file to edit is named in the README.

bash
zig build sdl3-app

That builds the sdl3 backend example where DVUI handles the main loop, and the README calls it a good place to start, pointing at `frame()` inside `./examples/app.zig`. If you prefer a repository that already contains the examples wired up, `dvui-demo` is described as a template repository that also includes them.

The documentation builds locally too, with an option to render images:

bash
zig build docs -Dgenerate-images

The output lands at `./zig-out/docs/index.html`, and the same documentation is published online.

Accessibility is opt-in through a build flag rather than on by default:

bash
zig build -Daccesskit

That enables AccessKit, and the README links a separate accessibility document.

If your project needs a different entry point than the examples, `build.zig` and `build.zig.zon` at the root are where the targets are declared, and the standard Zig build option convention is what the examples use for the Vulkan renderer selection.

The repository is not bare: there is a `vendor/` directory, a `.gitmodules` file for vendored dependencies, `tools/` for repository tooling, and a `package.json` with a `typecheck` script running `tsc -p ./tsconfig.json`. That JavaScript tooling exists for the web backend's type declarations, since `src/backends/web.js` and `src/backends/web.d.ts` are the package's `main`, `module` and `types` entries.

Version pinning is the first thing to get right

DVUI tracks Zig's own release cadence closely, and the README's version note is the first line after the title.

It states the project is tested with Zig v0.17.0, and for Zig v0.16.0 instructs you to use tag v0.5.0. The release history confirms the pattern: v0.3.0 was released for Zig 0.14.1, v0.4.0 for Zig 0.15.2, and v0.5.0 is titled for Zig 0.16.0.

The dates are uneven. v0.3.0 shipped on 2025-08-30, v0.4.0 on 2026-04-16, and v0.5.0 on 2026-10-13. The last push was on 2026-10-15, two days after the release tag, which is what an in-development branch looks like.

For an adopter this means two distinct failure modes to avoid. Building against a Zig version newer than the one the tag was tested with will surface as compile errors in a GUI library whose internals touch standard library types closely. Building `main` against an older Zig than the one it targets fails differently. Pin both the Zig version and the DVUI tag together, following the mapping the README gives.

The absence of a changelog in the top-level listing is worth noting. The top-level entries are `.github/`, `.gitignore`, `.gitmodules`, `LICENSE`, `README.md`, `build.zig`, `build.zig.zon`, `docs/`, `examples/`, `package.json`, several `readme-*.md` documents, a screenshot, `src/`, `tools/`, `tsconfig.json` and `vendor/`. Release information is in the tags and in the online devlog rather than in a file in the repository.

The license metadata disagrees with itself

There is a discrepancy worth resolving before you build a product on this.

The repository's license is recorded as a custom licence that GitHub cannot classify, with a pointer to the LICENSE file. But `package.json` in the repository declares `"license": "MIT"`, and the README does not state a licence identifier at all.

For a package published under `src/backends/web.js` as its main entry, `package.json` is what a JavaScript toolchain reads. For a Zig dependency pulled as a source package, the LICENSE file is what governs. Those two can disagree, and here they appear to.

The safe procedure is to read `LICENSE` in the repository root and treat it as the authoritative statement, rather than trusting either the GitHub license classifier field or the npm metadata field. This article is not giving legal advice; it is flagging that the two metadata sources in this repository do not agree, which is exactly the situation where you check the actual file.

One further detail from `package.json` is worth knowing before you rely on the npm entry: its `test` script is a placeholder that prints an error and exits with status 1, so `npm test` in this repository does not run tests. The `typecheck` script does work, invoking TypeScript 5.9.3 against the repo's `tsconfig.json`.

The maintainer runs a public devlog at david-vanderson.github.io, and the project is discussed on the Zig Discord in `#dvui` and `#dvui-help` channels and in GitHub Discussions.

Where DVUI is the wrong choice

The fit is narrower than a general GUI toolkit, and the reason is the language and the maturity.

DVUI is Zig only. There is no C API, and a project whose UI layer is C++ has no path to it short of writing bindings yourself, which is a different project from using DVUI.

Immediate mode is also a real constraint, not a style preference. The API is immediate mode by definition, and there is no retained widget hierarchy in the design. For a form-heavy or text-heavy enterprise interface with hundreds of widgets that change rarely, an immediate mode API means re-evaluating the whole UI each frame, which is a different performance and code-organisation profile from a retained tree. DVUI's own answer to that, processing every input event, is aimed at low frame rate situations rather than at dense forms.

The backend gaps decide backend choice for you. If you need the web target you get `web-app` and nothing else. If you need SDL3GPU as a full application, the matrix says todo.

The alternative to weigh is the ecosystem native to your language. Zig projects that use raylib-zig directly get a rendering library and no GUI layer, and building your own immediate mode layer over raylib is what DVUI itself does. The difference in approach is scope: DVUI is a finished widget set with icons, fonts, file dialogs, touch handling and accessibility support, backed by someone else maintaining the backend matrix. Writing it yourself gives exactly the widgets you need and exactly the backends you support, at the cost of maintaining it.

DVUI is also young enough that the version tag and the Zig version are a single decision, and v0.5.0 as a version number says as much about the API's stability as any documentation would.

Editorial conclusion

Adopt DVUI if you are writing Zig and want to either own the main loop or drop a HUD onto an existing window without restructuring that application, because the standalone and ontop modes are unusual and useful, and because `zig build sdl3-app` gets you a running window you can edit in `./examples/app.zig`. Do not adopt it expecting feature parity across backends: the README's own matrix lists `todo` for SDL3GPU as an app, `todo` for GLFW standalone, and `none` for both Web standalone and Web ontop, so pick a backend your mode supports. Verify three things first: that your Zig version matches, since the README says it is tested with Zig v0.17.0 and points to tag v0.5.0 for Zig v0.16.0, and that tag is itself pinned to Zig 0.16.0; that the license question is settled, because the repository's license field records a custom licence GitHub cannot classify while `package.json` declares MIT, which is a discrepancy to resolve against the LICENSE file rather than either metadata field; and that your target platform has a backend, given DX11 is Windows-oriented and wio, pugl and the web target differ in how they present OpenGL. The last push was on 2026-10-16 and v0.5.0 shipped on 2026-10-13.

Frequently asked questions

Which Zig version does DVUI support?

The README states it is tested with Zig v0.17.0, and for Zig v0.16.0 you should use tag v0.5.0. Earlier tags map the same way: v0.4.0 for Zig 0.15.2 and v0.3.0 for Zig 0.14.1.

How do I build a first DVUI example?

Run `zig build sdl3-app`, which uses the SDL3 backend with DVUI handling the main loop. The README points you at `frame()` inside `./examples/app.zig` as the place to change.

What backends does DVUI support?

SDL2, SDL3, Web, Raylib through the C API and through raylib-zig, DX11, OpenGL with GLFW, and wio with either OpenGL or Vulkan selected by `-Drenderer=vulkan`. The README also publishes a matrix showing that SDL3GPU has no app example yet, GLFW has no standalone example, pugl has no ontop example, and Web has neither standalone nor ontop.

What does the ontop mode in DVUI do?

It draws a debug HUD on top of an existing application or game that you did not write, using examples named `*-ontop.zig`. The README describes DVUI as appropriate for either a whole UI or debugging on top of an existing application.

How do I enable accessibility in DVUI?

Add the flag `-Daccesskit` to `zig build`, which enables AccessKit. The README links a separate accessibility document for the details.

How is DVUI licensed?

The repository's license field records a custom licence that GitHub cannot classify, while package.json declares MIT. The LICENSE file in the repository root is the source to check, since the two metadata sources disagree.

Official sources

  1. david-vanderson/dvui on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/david-vanderson-dvui.svg)](https://hysenlabs.com/projects/david-vanderson-dvui)