Hello-world desktop app in one Go binary: embedded page, GTK webview, tray, pacman package. Companion sample for the buildr.fun blog post on shipping desktop Linux apps without Electron.
  • Go 77.3%
  • Shell 16.4%
  • HTML 6.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
billotp 3e0dcf75b5 feat: buildr.fun-style tray icon; README + CHANGELOG
- packaging/icons: SVG source (favicon geometry: dark rounded tile, three
  amber bars) rendered to 32px tray PNG and 128px launcher icon
- PKGBUILD installs both hicolor sizes
- README: layout map, test lane, icon, changelog link
- CHANGELOG.md: Keep-a-Changelog 0.1.0 entry
2026-11-14 10:09:52 +01:00
packaging feat: buildr.fun-style tray icon; README + CHANGELOG 2026-11-14 10:09:52 +01:00
.gitignore feat: hello-world desktop app in one Go binary 2026-11-14 09:26:45 +01:00
CHANGELOG.md feat: buildr.fun-style tray icon; README + CHANGELOG 2026-11-14 10:09:52 +01:00
desktop.go feat: hello-world desktop app in one Go binary 2026-11-14 09:26:45 +01:00
go.mod feat: hello-world desktop app in one Go binary 2026-11-14 09:26:45 +01:00
go.sum feat: hello-world desktop app in one Go binary 2026-11-14 09:26:45 +01:00
gtk.go feat: hello-world desktop app in one Go binary 2026-11-14 09:26:45 +01:00
index.html feat: hello-world desktop app in one Go binary 2026-11-14 09:26:45 +01:00
LICENSE feat: hello-world desktop app in one Go binary 2026-11-14 09:26:45 +01:00
main.go test: cover the shared server face; wire tests into PKGBUILD check() 2026-11-14 10:06:23 +01:00
README.md feat: buildr.fun-style tray icon; README + CHANGELOG 2026-11-14 10:09:52 +01:00
runui_stub.go feat: hello-world desktop app in one Go binary 2026-11-14 09:26:45 +01:00
server_test.go test: cover the shared server face; wire tests into PKGBUILD check() 2026-11-14 10:06:23 +01:00
tag_off.go feat: hello-world desktop app in one Go binary 2026-11-14 09:26:45 +01:00
tag_on.go feat: hello-world desktop app in one Go binary 2026-11-14 09:26:45 +01:00
tray.go feat: hello-world desktop app in one Go binary 2026-11-14 09:26:45 +01:00

go-webview-hello icon

go-webview-hello

The smallest runnable version of the pattern described in "Ship a desktop Linux app as one Go binary": one binary, no Electron, no CGO.

Talk is cheap. This is the code:

  • an embedded page (//go:embed of a single HTML file — no SPA toolchain),
  • an http.Server on the loopback serving it plus one JSON endpoint,
  • a GTK webview window (-tags desktop) through glaze / purego over the distro's WebKitGTK,
  • a tray icon (fyne.io/systray, plain DBus, no GTK) in the buildr.fun favicon style (SVG source),
  • the close-button veto: the window's delete-event fires before GTK decides to destroy, so "close" hides to tray instead of quitting,
  • one shutdown funnel (sync.Once) for window-quit, tray-quit and signals,
  • a PKGBUILD whose version is derived from the git checkout so every commit is a strictly newer package under vercmp.

Layout

main.go        shared: embedded page, loopback server, /api/hello JSON
tag_on.go      desktopTag = true   (only with -tags desktop)
tag_off.go     desktopTag = false  (plain go build)
runui_stub.go  headless stub so one tree compiles both faces
desktop.go     desktop face: window, tray, signals, shutdown funnel
gtk.go         close-button veto via purego dlopen("libgtk-3.so.0")
tray.go        tray menu; GTK effects go through w.Dispatch
index.html     the whole "SPA"
packaging/     PKGBUILD, desktop entry, icons (SVG source + rendered PNGs)

Run it

Headless face (server only):

go build -o hello .
./hello
# serving on http://127.0.0.1:NNNNN — Ctrl-C to stop

Desktop face (server + window + tray):

go build -tags desktop -o hello-desktop .
./hello-desktop

Close the window: it hides. Bring it back or quit from the tray icon.

Test it

go test -v .               # headless face
go test -v -tags desktop . # desktop face (same suite; the GTK loop itself
                           # cannot run under go test — that is what the
                           # packaged check() and a real run are for)

Package it (Arch)

cd packaging && makepkg -f
sudo pacman -U go-webview-hello-*.pkg.tar.zst

check() inside the PKGBUILD runs both vets and both test suites before anything is packaged. The app shows up in your launcher; pacman -R go-webview-hello removes every file it ever laid down.

See CHANGELOG.md for what changed and when.

Requirements

Linux, Go ≥ 1.27 to build. At runtime the desktop face needs the system web stack — webkit2gtk-4.1 gtk3 glib2 dbus — nothing else; the binary dlopens libgtk-3.so.0 at startup and refuses to run on a GTK4/webkitgtk-6.0 stack (one process, one GTK major version).

License

MIT