Capy: Cross-platform native GUIs in Zig

I guess I’m making a post here as the old one in r/Zig got deleted.

I’ve been creating Capy since about two years.

One of the main differentiatiors between Capy and other projects is that it uses native widgets. This makes accessibility, shortcuts and other features much more consistent with the OS and what the user is accustomed to.

You can find the source code and usage instructions here:

(check the website too:

Here’s some code

const capy = @import("capy");
const std = @import("std");

pub fn main() !void {
    try capy.backend.init();

    var window = try capy.Window.init();
    try window.set(
        capy.Column(.{ .spacing = 10 }, .{ // have 10px spacing between each column's element
            capy.Row(.{ .spacing = 5 }, .{ // have 5px spacing between each row's element
                capy.Button(.{ .label = "Save", .onclick = buttonClicked }),
                capy.Button(.{ .label = "Run",  .onclick = buttonClicked })
            // Expanded means the widget will take all the space it can
            // in the parent container
                capy.TextArea(.{ .text = "Hello World!" })

    window.resize(800, 600);;

fn buttonClicked(button: *capy.Button_Impl) !void {"You clicked button with text {s}", .{button.getLabel()});

Very nice to see, an easy to use UI library is something that the Zig ecosystem has been missing, IMHO.

One question though, when the README says:

  • Uses the target OS toolkit

…what does this mean on systems like Linux? :upside_down_face:

Good question! I answered to it in part in the README:

As there’s no “official” GUI library for Linux, GTK 3 has been chosen as it is the one that works and can be configured on the most distros. It’s also the reason Libadwaita won’t be adopted, as it’s meant for GNOME and GNOME only by disallowing styling and integration with other DEs.

But to go deeper, for Linux, there are two big GUI toolkits supported by most DEs: GTK and Qt, the simplest to integrate in Capy was GTK so I went with it.

I also couldn’t choose other smaller GUI toolkits because the whole point of “native” UI is for it to be integrated with the rest of the desktop, and the truth is most DEs on Linux only have integrated customization options for GTK (GNOME, Mate…) and/or Qt (LXQT, KDE…)