A desktop configuration editor for streamdeckd. Build your Stream Deck layouts visually instead of hand-editing JSON.
streamdeckui-wails is a Wails app (Go backend, React + TypeScript frontend) that talks to a running streamdeckd over D-Bus. It gives you:
- Live key and knob previews rendered exactly as the daemon draws them
- Drag-and-drop layer stacks for every key and LCD segment
- Per-application profiles so buttons change with the focused app
- Page management with reordering that fixes up your
SwitchPagelayers for you - Deck, page, and key backgrounds from static images or background handler modules
- Undo/redo, import/export, and explicit control over when changes reach the daemon and disk
It edits the same config streamdeckd already has in memory, so nothing you do here is permanent until you commit it.
- A running streamdeckd on your session bus — the UI is a client and will not start without it
- Go 1.25 or newer, and the Wails v2 CLI:
go install github.com/wailsapp/wails/v2/cmd/wails@latest
- Node.js and npm for the frontend
- GTK 3 and WebKit2GTK development packages:
# Debian/Ubuntu sudo apt install libgtk-3-dev libwebkit2gtk-4.0-dev # Fedora sudo dnf install gtk3-devel webkit2gtk4.0-devel # Arch sudo pacman -S gtk3 webkit2gtk
-
Build and run:
wails build ./build/bin/streamdeckui-wails
-
Pick your device from the toolbar dropdown and start editing.
For development with hot reload of frontend changes, use wails dev. That also serves a dev build on http://localhost:34115 with the Go methods available from browser devtools.
The toolbar separates "the daemon knows about this" from "this survives a restart":
- Auto-update (the circular arrows toggle) pushes every edit to the daemon after a short debounce so you can see it on the hardware immediately. It is on by default and remembered between sessions.
- Send pushes the current config to the daemon on demand. A dot appears when auto-update is off and you have unsent changes.
- Commit writes the daemon's config to disk. A dot appears whenever you have uncommitted changes.
- Reload throws away in-memory changes and re-reads from disk.
Undo and redo are bound to Ctrl+Z and Ctrl+Shift+Z and keep the last 30 states.
Click any key or LCD segment to select it; the editor below follows your selection.
- Test Press Key fires a real press on the selected key through the daemon, so you can check a
CommandorKeybindlayer without reaching for the hardware - Copy and Paste move a whole key or knob, layers and profiles included, to another position or page
- Pages are selected from the numbered pills, reordered with the arrows beside them, and added or deleted from either end of the row
- If the selected device is unplugged the grid dims and says so. Edits still apply and take effect when it reconnects
Each key and each LCD segment holds a stack of layers. The top of the list is the top of the stack.
- Drag handlers in from the search panel on the right, or click to append
- Reorder by dragging rows; drop indicators show where the layer will land
- Visual and Input toggles decide whether a layer draws, handles input, or both. They are disabled for handlers that cannot do that job
- Rename any layer so a stack of three
Textlayers is still readable - Input event filtering narrows a layer to specific events — turn clockwise/anticlockwise, press, screen tap, long tap and swipe on knobs; press and release on keys. Ticking nothing means every event
- Layers whose handler module is not loaded are flagged but kept as-is, so opening a config on a machine without all your plugins will not silently destroy it
A key can look and behave differently depending on the focused application.
- Default is the fallback profile, used when nothing more specific matches
- Named profiles are matched against the focused application
- All apps holds layers that apply to every profile. Each profile decides where they sit in its own stack using the Application independent layers marker, and drops them at the bottom if it has no marker
Backgrounds are configurable at three levels, each drawn over the one before it: deck, then page, then the individual key or LCD segment. Each one takes either a static image file or a background handler module along with that module's own fields. Deck and page level images are sliced across the grid, so a single wallpaper can span the whole device.
The Settings tab manages the list of compiled Go plugin (.so) paths that streamdeckd loads. Adding or removing one needs a daemon restart to take effect. See streamdeckd-modules for examples.
Previews are built in two passes so the grid never sits empty waiting on the daemon:
- The Go backend composites the backdrop locally — black, then the deck grid slice, the page grid slice, and the key's own background — and hands it straight back.
- If the key has visual layers, it asks the daemon to render them via
GetLayersExampleand composites the result over that backdrop.
Results are cached in memory and keyed on everything that affects the image, so switching pages and profiles is instant. If a preview goes stale, Refresh Previews clears it. When the daemon cannot render a stack — a missing handler, or a disconnected device — the backdrop is shown rather than nothing.
- streamdeckd - the daemon this configures
- api - the Go library and D-Bus interface it talks over
- streamdeckd-modules - example plugins
- driver - the underlying Stream Deck driver
See LICENSE for details.
