gowa-ui
July 14, 2026 · View on GitHub
A web dashboard for go-whatsapp-web-multidevice (gowa).
The whole app builds into one HTML file with no external dependencies. Host it anywhere (or just open it in a browser) and point it at your gowa server. The backend stays a pure API; the UI ships separately — same idea as CLIProxyAPI and its Management Center.
Built with React 19, TypeScript, Vite, Tailwind CSS 4, and shadcn/ui.
Status: feature parity with gowa's embedded dashboard. Tagging a
v*release publishesgowa-ui.html.
How to use it
Pick one:
- Served by gowa — gowa downloads the latest
gowa-ui.htmlrelease and serves it at/. (Planned; lands with the parity cutover.) - Host it yourself — put the built file on any static host (GitHub Pages works). On first load, enter your server URL and basic-auth credentials; they're saved in
localStorage. - Open the file directly — download
gowa-ui.htmlfrom a release and open it in a browser. Works, but some browser APIs need an HTTP origin, so hosting is better for daily use.
What your gowa server needs
The dashboard talks to gowa from the browser, so the server needs a few cross-origin features:
- CORS — allow the
AuthorizationandX-Device-Idheaders. - REST auth —
Authorization: Basic <base64(user:pass)>header. - Device selection —
X-Device-Idheader (URL-encoded) or?device_id=query. - WebSocket auth —
/ws?device_id=<id>&authorization=<base64(user:pass)>. Browsers can't set headers on WebSocket connections, so the credential goes in the query string — use TLS. - Server info —
GET /app/info(version, media size limits).
Development
cp .env.example .env # set VITE_DEFAULT_SERVER_URL if your gowa isn't on :3000
npm install
npm run dev
Then connect the app to your server, either way:
- Directly — enter
http://localhost:3000on the connect screen (needs a gowa build with the CORS features above). - Via the dev proxy — enter
http://localhost:5173/gowainstead; Vite forwards everything (WebSocket included) toVITE_DEFAULT_SERVER_URL, so CORS doesn't matter.
Other scripts: npm run build (single-file production build into dist/index.html), typecheck, lint, format, preview.
Single-file rules
The build must stay one file with zero external requests:
- No
import()orReact.lazy— code splitting breaks single-file output. - No CDN scripts, external fonts, or remote images — everything is bundled and inlined.
HashRouteronly — it survivesfile://and any mount path.
CI checks that dist/ contains exactly one file.
Regenerating the logo
The source logo lives in the backend repo: src/views/assets/gowa.svg. It's ~864 KB (an SVG wrapping embedded 1024px rasters), so we don't inline it — we bundle rasterized copies instead. To regenerate them after a branding change:
rsvg-convert -w 128 -h 128 gowa.svg -o /tmp/gowa-logo.png
cwebp -q 90 /tmp/gowa-logo.png -o src/assets/gowa-logo.webp # sidebar logo
rsvg-convert -w 64 -h 64 gowa.svg -o /tmp/gowa-favicon.png # then re-embed as the
# base64 favicon in index.html
Releases
Every v* tag publishes exactly one asset named gowa-ui.html (plus a .sha256 checksum). The gowa backend fetches releases/latest by that exact name, verifies the checksum, caches the file, and serves it at /. Don't rename the asset.
Roadmap
- M0 — scaffold: single-file build, app shell, dark mode, CI/release workflows
- M1 — connect screen, device manager, QR/pair-code login, logout/reconnect, WebSocket events
- M2 — send suite (message, image, file, video, sticker, contact, location, audio, poll, link, presence)
- M3 — message actions (delete, revoke, react, update, read, star, forward) + call reject
- M4 — groups (create, join, info, participants, settings, invite links)
- M5 — account (avatar, push name, privacy, contacts) + newsletters
- M6 — chats (list, message viewer, composer, pin, archive, disappearing timers)
- M7 — parity audit vs the embedded dashboard → v1.0.0
- v1.1.0 — per-device webhook editor (URL, secret, events, TLS verify) on the device card
- v1.1.1 — group participants viewer: table with admin badges + inline add/promote/demote/remove
Still to do: Chatwoot config module, full WebAuthn passkey flow.