wails.md

Wails desktop apps

Use Wails when the app is a desktop product, not merely because it has a web view. Go should own application logic; the frontend should render state and call bindings.

Read web.md alongside this file for frontend CSS, accessibility, and semantic token guidance. Read packaging.md for every Wails setup; desktop apps need a packaging story from the start.

Build/tooling

Start from the baseline in mise.md; keep its fmt, modernize, lint, vuln, race-enabled test, and check tasks. Then add Wails/frontend tools and tasks in mise, not Taskfile:

[tools]
go = "latest"
node = "22"
"go:github.com/wailsapp/wails/v2/cmd/wails" = "latest"
"go:golang.org/x/vuln/cmd/govulncheck" = "latest"
golangci-lint = "latest"
nfpm = "latest"

[env]
_.path = ["{{config_root}}/frontend/node_modules/.bin"]

[vars]
wails_build_args = "-tags webkit2_41 -trimpath"
wails_ldflags = "-s -w"

[tasks.dev]
run = "wails dev -tags webkit2_41"

[tasks.build]
run = '''
wails build {{vars.wails_build_args}} -ldflags "{{vars.wails_ldflags}}"
'''

On Linux, include -tags webkit2_41 for WebKitGTK 4.1. Missing it often fails late and unclearly.

If the app exposes an About/version surface or release metadata, choose a project-owned version policy and inject the resolved value with -X, as in the CLI guidance.

Frontend stack

Use the existing package manager if one exists. Ask before introducing a new one. Use Svelte 5 + TypeScript + Vite for Wails frontends. Tailwind and shadcn-svelte are optional project choices, not defaults to add blindly.

Frontend checks usually split from backend checks:

  • backend: golangci-lint fmt, golangci-lint run --fix, govulncheck, tests
  • frontend: typecheck, lint, format, unit tests when present
  • combined: mise run check

Binding and event rules

  • Do not edit generated frontend/wailsjs/ files.
  • Add Go methods/types to trigger Wails TypeScript generation.
  • Prefer explicit event names and typed payloads for async pipelines.
  • Go owns queues, cancellation, filesystem access, keyring access, and API clients.
  • Svelte owns local rendering state and user interactions.

Errors

For user-facing backend errors, send a structured shape the frontend can render: code, message, optional suggestion, optional details. Do not make the frontend parse arbitrary English when the backend can categorise the failure.

Packaging

Read packaging.md for nFPM, desktop files, icons, and WebKit dependencies.