Repository navigation
Web UI: port from SvelteKit to Rust (Dioxus) #4633
Description
Description
I've built this out on my fork to see whether it holds up before asking for anyone's time:
https://github.com/billy-doyle/iggy/tree/dioxus-web-ui
It's a complete port. If a Rust UI isn't wanted, just let me know. I've used Dioxus before and thought it was a good fit here. I like not having the second toolchain and npm dependency tree, but understand if that isn't desired.
I built this with Claude Code and have reviewed the changes myself. Each PR would say what the agent wrote, as CONTRIBUTING asks.
Here it is running locally:
Affected area / component
Web UI
Proposed solution
A Dioxus web UI in core/web_ui (crate iggy-web-ui), built to WebAssembly with dx and
embedded by iggy-server under /ui, the same way the Svelte static build is today.
Scope is the Svelte UI's working features, nothing more:
- Sign-in and sign-out, dashboard layout, overview stats
- Streams, topics, partitions: browse, create, edit, delete, add and remove partitions
- Messages: paging, and an inspector with string/JSON/XML decoders and user headers decoded by kind
- Users: list, search, create (with the global/stream/topic permissions editor), edit
- Web UI settings: light/dark/system theme and the refresh interval, plus a refresh button
Pages that are placeholders in the Svelte UI (Clients, Logs, Terminal, the Server settings mock,
Delete user, Edit permissions) are left out rather than ported as placeholders.
Operators should see no change:
apache/iggy-web-uikeeps its name, port 3050 (PORT),GET /healthz, andPUBLIC_IGGY_API_URL.
It becomes an nginx image serving the bundle, and a start-up script writes the API URL into a
config.jsonthe UI reads at run time.- The Helm chart is unchanged.
http.web_uiworks as before. - The crate takes over
web/package.json's version, soweb-ui-*image tags continue.
Differences from the Svelte UI, all small:
- Logout calls
DELETE /users/logout, the route the server has (see Web UI: ApiSchema.ts doesn't match the server's HTTP routes for logout and user updates #4214). - XML validation uses
roxmltree. The Svelte check only works in Firefox, so in Chrome any
payload passes as XML. - The JSON decoder still expands JSON documents stored as strings, but no longer turns strings
like"123"into numbers. - Byte sizes are shown in readable units (
456.39 GiBrather than478456976 KiB). - The theme and refresh interval persist across reloads. The interval used to reset to 4s.
- Rejected requests show the server's
reason(for example "Invalid credentials").
Build and CI:
dxis pinned by version and SHA-256 inscripts/ci/install-dx.sh, and the script fails if it
drifts from thedioxusversion inCargo.lock. Dioxus only ships glibc builds, so the Alpine
server image builds the bundle in a Debian stage.- A
rust-web-uiCI component runs the normal Rust checks plus wasm32 clippy and the bundle. - The bundle is about 1.08 MB of WebAssembly (381 KB gzipped).
- The crate is a workspace member, so workspace builds compile Dioxus for the host, much like the
bench dashboard's Yew frontend does today. - Third-party licenses pass
scripts/ci/third-party-licenses.sh --validatefor both bundles, and
the server's LICENSE-binary lists the UI's crates instead of npm packages.
How it was checked: unit tests (33), and a headless-Chrome suite of 37 checks run against the
server's embedded UI, a separate origin through nginx, and the built iggy-web-ui and apache/iggy
images. Fork CI run.
Possible PR plan, one open at a time, each merging on its own:
- Crate, sign-in, streams browser (additive, the server keeps serving Svelte)
- CI for the crate
- Overview
- Stream/topic/partition management
- Users
- Message inspector
- Theme and refresh settings
- Standalone image (built but not yet published)
- Switch-over: server embeds Dioxus, publishing repointed,
web/removed
Happy to regroup this into fewer or larger PRs, or to go about it another way.
Alternatives considered
- Keep Svelte. No migration cost, but like I said above, single toolchain.
- Yew, which
core/bench/dashboard/frontendalready uses. I'm more comfortable with Dioxus and really like the ergonomics. - Leptos. Haven't used myself but know it is a popular alternative in rust as well.
- Sharing types with the server through
iggy_common. It doesn't build for wasm32 (tokio with
net), so the UI keeps its own serde types for the HTTP JSON. Those could later be checked
against the OpenAPI document proposed in feat(server): add an OpenAPI document for the HTTP API #4212.
Contribution
- I'm willing to submit a pull request to implement this feature
Good first issue
- I think this could be a good first issue for a new contributor
Activity
billy-doyle commentedon Oct 25, 2026
Thanks for the go-ahead on Discord. I'm about to open the first PR, so here's the plan I'll follow.
Since opening this issue I've rebased onto current
master. #4625 added a Metadata changes page to theSvelte UI, so I've ported that too, which makes the plan 10 PRs instead of 9. The full series is here:
https://github.com/billy-doyle/iggy/tree/dioxus-web-ui-v2
I'll keep one PR open at a time and open the next one after the previous one merges. Each one says which
part it is. Until a part has its PR, its "preview" link shows just that part's diff on my fork.
apache/iggy-web-uiimage, built but not published yet (preview)web/removed, closes this issue (preview)PR 2 only touches CI config and scripts, so I can open it first if you'd rather have CI in place before
any UI code. I'm also happy to group these differently if that's easier to review.