What's New in v9.0.0
🚀 Major Release: Standalone gowa-ui Dashboard, Pure API Backend & Fiber v3
This release splits the web dashboard out of the binary. gowa is now a pure API server that downloads the latest gowa-ui release at runtime, verifies it, caches it, and serves it at / — same URL, same basic auth. The second breaking change is the move to Fiber v3, which reshapes the Go-level API for anyone embedding gowa as a library while leaving HTTP consumers untouched. This release also adds GET /app/info and cross-origin WebSocket auth so standalone UIs can talk to the server, and fixes sent messages being lost under SQLite write contention plus percent-encoded chat_jid path params never matching.
⚠️ Breaking Changes
Embedded Dashboard Removed (#766)
src/views/(56 Vue components), thego:embedbundle, the HTML template engine, and the basic-auth token echo middleware are gone; the dashboard now lives in its own repo — aldinokemal/gowa-ui (React 19 + Vite + Tailwind 4 + shadcn/ui), released as a single self-containedgowa-ui.html- The server fetches that asset at runtime and serves it at
/— same URL, same basic auth, so a normal browser-based deployment behaves as before after the first download APP_UI_ENABLED=falseturns/into a JSON banner for pure-API deployments- Air-gapped installs: set
APP_UI_AUTO_UPDATE=falseand pre-seedstorages/ui/, or disable the UI entirely
Fiber v3 Upgrade (#764)
- Fiber core
v2.52.14→v3.4.0, GoFiber utilities tov2.1.2, and the WebSocket add-on fromgithub.com/gofiber/websocket/v2togithub.com/gofiber/contrib/v3/websocket v1.2.1 - Relevant if you embed
gowaas a library or build against its handlers: Fiber v3 changes the context, binding, static middleware, configuration, testing, and utilities APIs - The whole Fiber-dependent surface was migrated in one pass — REST handlers, middleware, request binding, query parsing, context propagation, trusted-proxy/listen configuration, static delivery, and tests — so no mixed v2/v3 behavior is retained
- HTTP API consumers are unaffected: routes, payloads, device scoping, and WebSocket behavior are preserved, the plaintext
APP_BASIC_AUTH=user:secretcontract is kept via a constant-time custom authorizer, and generated QR/media URLs stay correct through the Fiber v3 request scheme API
✨ New Features
Runtime-Downloaded Dashboard (#766)
- New
src/infrastructure/uiassetfetches the latestgowa-ui.htmlrelease asset ofAPP_UI_REPO(defaultaldinokemal/gowa-ui), compares sha256 digests, uses ETag-conditional requests, and writes an atomic cache atstorages/ui/ - Serves the cached asset with ETag/304, auto-updating every
APP_UI_UPDATE_INTERVAL(default3h, ±10% jitter), and falls back to a graceful offline page when the cache is empty and GitHub is unreachable - Config:
APP_UI_ENABLED,APP_UI_AUTO_UPDATE,APP_UI_REPO,APP_UI_ASSET_NAME,APP_UI_UPDATE_INTERVAL,APP_UI_GITHUB_TOKEN(optional, raises the GitHub API rate limit) APP_UI_ASSET_SHA256is an operator-supplied supply-chain pin: when set, the server refuses to download or serve any asset whose sha256 differs — checked against the release digest before download, against the downloaded bytes, and against the cache on boot
Server Metadata Endpoint (#766)
- Adds
GET /app/inforeturning{version, os, base_path, max_file_size, max_video_size, max_image_size, chatwoot_enabled}, replacing the HTML template injection that standalone UIs can no longer rely on
Cross-Origin WebSocket Auth & CORS (#766)
- Browsers cannot set headers on a WebSocket handshake, so
/ws?authorization=<base64(user:pass)>is now accepted and validated by the same constant-time basic-auth authorizer — TLS is required in production - CORS is widened and moved ahead of statics:
AuthorizationandX-Device-Idare allowed with explicit methods, and QR PNGs plus media under/staticsnow carry CORS headers
🐛 Bug Fixes
Sent Messages Lost Under Write Contention (#766)
wrapSendMessagestored sent messages in a detached goroutine with a 2s budget while SQLite'sbusy_timeoutis 30s, so during history-sync contention the deadline could expire between the chat-bump write and the message insert — leaving a bumped chat with a missing message- The message row is now written first (a partial failure loses only the invisible timestamp bump), the budget is raised to 15s, and failure logs carry the message ID and recipient
Percent-Encoded chat_jid Never Matched (#766)
- Fiber does not URL-decode path params, so any client that percent-encodes the JID path segment (gowa-ui and most HTTP libraries) got empty results from
/chat/{chat_jid}/*even though the rows existed - All four chat handlers now
url.PathUnescapethe param — a raw@is unchanged, so existing clients see no behavior change — and malformed escapes return the standard 400 JSON envelope - OpenAPI notes added on all four
chat_jidparams
Contact Display Names in Listings
MyListContactsreturned onlyFullName, so contacts saved without one came back with an empty name- Contact listings now apply the same saved → push → business name precedence used elsewhere, with unit test coverage for the fallback order
🔧 Technical Improvements
Dependency Updates
go.mau.fi/whatsmeow: refreshed to the latest snapshot (v0.0.0-20260718134955-fac667d55293)- Fiber and its add-ons moved to v3 — see Breaking Changes above for the full list
- Dropped
github.com/gofiber/template/html/v2along with the template engine;go.mau.fi/utiland assorted indirect dependencies refreshed
Cleanup
- Removed dead Chatwoot client code and its now-redundant test scaffolding, a stale error constant, and obsolete planning docs
- Logo moved to
gallery/gowa.svg; obsolete dashboard screenshots removed from the gallery
Release Metadata
AppVersionis nowv9.0.0, so runtime status matches the published release tag
What's Changed
- chore: upgrade Fiber to v3 by @aldinokemal in #764
- feat!: standalone gowa-ui dashboard — pure API backend + runtime-downloaded UI by @aldinokemal in #766
- chore!: bump version to v9.0.0 by @aldinokemal
- chore: remove deadcode by @aldinokemal
- chore(gallery): remove obsolete dashboard screenshots by @aldinokemal
- fix(contacts): use fallback names in contact listings by @aldinokemal
- chore: update whatsmeow to latest by @aldinokemal
Full Changelog: v8.11.0...v9.0.0