Dioxus builds web desktop and mobile apps in pure Rust

Dioxus is a Rust cross-platform app framework that builds web, desktop, mobile, and server apps from one codebase. Run dx serve --hotpatch and changed Rust code drops into the running app. There is no rebuild, so you see the change instead of waiting on a compile.

Key Takeaways

  • One Rust codebase builds web, desktop, mobile, and server versions of an app.
  • Hot patching drops changed Rust code into the running app, skipping the rebuild.
  • You style apps with plain HTML and CSS, Tailwind included.
  • Web builds start near 50 KB and portable desktop binaries stay under 3 MB.
  • The 0.8 line is still alpha, so pin a version and expect churn.

What a Rust cross-platform app framework actually gives you

In Dioxus , a component is a plain Rust function that returns an Element. Markup lives inside an rsx! macro, and state comes from signals rather than hooks. A frontend developer will recognise that shape.

The project describes its state management as pulling ideas from React , Solid , and Svelte . A full counter component fits in ten lines.

fn app() -> Element {
    let mut count = use_signal(|| 0);

    rsx! {
        h1 { "High-Five counter: {count}" }
        button { onclick: move |_| count += 1, "Up high!" }
        button { onclick: move |_| count -= 1, "Down low!" }
    }
}

“One codebase” covers a lot of ground here. The same source builds a web app through WebAssembly and a desktop app through a system webview. It also produces iOS and Android binaries, plus a server-rendered version with hydration.

Platform-specific code still exists, though. The framework’s answer is to make calls into JNI, Objective-C, and web APIs easy.

You style apps with plain HTML and CSS. Tailwind support, v3 and v4, is wired into the CLI with no setup step, and there is no custom layout language to learn.

You also don’t start from a blank canvas. The 0.7 release shipped 28 first-party components built after Radix Primitives and shadcn/ui . Keyboard shortcuts and ARIA roles come already wired.

Grid of Dioxus first-party primitive components including tabs, dropdown menus, sliders, calendars, toasts, and dialogs
The 28 primitive components that ship with Dioxus 0.7
Image: DioxusLabs

How to start a Dioxus app and run it on the web

Install Rust first

Dioxus is a Rust framework, so a working cargo toolchain is the prerequisite. Install it through rustup if you don’t have it.

Install the CLI with cargo

Run cargo install --git https://github.com/DioxusLabs/dioxus dioxus-cli --locked to build the dx tool from source. If you’d rather not wait, cargo binstall dioxus-cli fetches a prebuilt binary instead.

Write a component

A component is a function that returns Element. Put your markup in an rsx! block and hold state with use_signal, as in the counter example above.

Serve it

Run dx serve. The dev server starts, and edits to markup, styles, and assets show up in milliseconds with no restart and no lost state.

Turn on Rust hot patching

Run dx serve --hotpatch to push changed Rust code into the running app. This one is still experimental, so keep plain dx serve as your fallback when it misbehaves.

Target another platform

Pass --platform to pick a target. dx serve --platform web runs in the browser, dx serve --platform android reaches an emulator or a plugged-in device, and desktop is the default.

Bundle for release

Run dx bundle. Web output gets AVIF image generation, WebAssembly compression, and minification. Desktop and mobile get platform installers, including .ipa and .apk files.

The edit loop and Rust hot patching

Compile time is the standing objection to writing user interfaces in Rust. A full rebuild on a mid-sized crate graph takes long enough to break your concentration.

The always-on tier is dx serve, which reloads markup, styles, and assets in milliseconds without restarting the process, so the app keeps whatever state it had.

An edit in the editor lands in the running app with no restart
Image: DioxusLabs

The experimental tier is dx serve --hotpatch, which runs a system the project calls Subsecond. It patches changed Rust code straight into the running binary, so logic edits skip the rebuild the same way markup edits already do.

Under the hood it’s a kind of incremental linking aimed at a live process. Subsecond has already been picked up outside this project, by Bevy and Iced .

The maintainers are blunt about the difficulty.

Hot-patching Rust code is no simple feat. To achieve a segfault-free experience, we recommend framework authors to tie into Subsecond’s minimal runtime.

Jonathan Kelley (Dioxus 0.7 release announcement)

Patching hooks in at explicit subsecond::call() sites, so it covers component code, event handlers, and server function logic. Add or remove a struct field between patches and your old state does not carry over. Dependency changes still force a full rebuild. Treat hot patching as a bonus rather than something to depend on. Even so, it’s the closest Rust has come to what fast refresh made routine in JavaScript years ago.

Server functions make it a fullstack framework

Most Rust user interface projects stop at the client and expect you to pick your own backend. Dioxus wires straight into axum , so the server half comes in the box.

You call server code from the client as if it were a local async function, and the request plumbing is generated for you. If your app is mostly forms and data, that cuts out a whole API layer you would otherwise hand-write.

The batteries are unusually complete for a UI framework. You get WebSockets, server-sent events, streaming, file upload and download, typed forms, middleware, and routing, all on top of axum 0.8. Server-side rendering with hydration, static site generation, and incremental regeneration all work. You can also adopt an existing axum backend instead of replacing it.

Bundle size, renderers, and where it runs

A web hello world lands around 50 KB, which the project positions as comparable to React. Desktop and mobile builds stay under 5 MB, and portable desktop binaries can come in under 3 MB. The tiny-dioxus reference build pushes a web bundle below 50 KB.

Those figures come from the project’s own documentation and describe a hello world. A real app with routing, a component library, and live data will weigh more. Treat 50 KB as a floor.

Renderer choice decides where an app can run, and the options are not all equally mature.

RendererTargetMaturity
web-sysBrowser, via WebAssemblyStable
Webview (wry)Desktop and mobileStable
Server-side renderingServer, with client hydrationStable
LiveViewServer-driven UI over a socketStable
WGPU / BlitzGPU-drawn native desktopExperimental
Freya (Skia)Native desktopThird party, experimental

The WGPU path is built on the Blitz engine, which borrows Firefox’s Stylo CSS engine and Linebender’s Vello renderer. The project says its output is often hard to tell apart from Chrome. Embedding in Bevy or running on embedded Linux works too, but none of that is the safe default.

The Blitz WGPU renderer drawing HTML and CSS natively, with no webview
Image: DioxusLabs

On desktop, memory behaviour should look familiar. Dioxus builds its webview windows on the wry and tao crates. Those are the same Tauri components most Rust desktop apps already sit on. Nobody has published a like-for-like memory test between the two, so any comparison you read is a guess.

Mobile is a real target, and JNI and Objective-C calls carry little overhead.

The same Dioxus app running side by side on an Android phone and an iPhone, showing an identical list interface
One Dioxus codebase running on Android and iOS
Image: DioxusLabs

Should you start a new project on Dioxus today?

The documented stable line is 0.7, and the release history shows 0.8 already shipping alpha builds. On a zero-point release line, public surfaces move between minor versions. So pin your version and read the migration guide before you upgrade.

The repository started in 2021 and carries about 720 open issues against 38,000 stars. It’s dual-licensed under MIT and Apache-2.0, the standard Rust arrangement, which clears a common procurement objection. A full-time core team works on Dioxus, paid for by FutureWei, Satellite.im, and the GitHub Accelerator. The stated long-term plan is to sustain it through paid enterprise tooling.

Teams already writing Rust have a strong reason to start now. They get a desktop or mobile front end without dragging in a JavaScript toolchain. Teams who aren’t fluent in Rust should wait. The framework is pleasant to use, but you still have to learn Rust first.