# Blitz: A Rust HTML/CSS Rendering Engine for Native Apps

> Blitz is a modular HTML/CSS rendering engine written in Rust, aimed at developers who want to render web content inside native applications without shipping a full browser. It is in beta, and the README says so plainly.

**DioxusLabs/blitz** — A radically modular HTML/CSS rendering engine

- Repository: https://github.com/DioxusLabs/blitz
- Website: https://blitz.is
- Stars: 4,207 · Forks: 214
- Language: Rust
- License: Apache-2.0
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/dioxuslabs-blitz

## What Blitz Solves and Who It Is For

Blitz is an HTML and CSS rendering engine that runs inside a Rust application. The README describes it as "a radically modular HTML/CSS rendering engine" and frames the motivation bluntly: "the browser is bloated for the basic use case of rendering HTML/CSS." If you need to display a Wikipedia page, a markdown file, or a styled form inside a native window, pulling in a full browser runtime is a heavy answer. Blitz is the lighter one.

The audience is narrow and specific. The README says Blitz "is usable for making apps if you are an early adopter and willing to live on the bleeding edge." That is not marketing hedging; it is a status statement. The project is in beta, and the README lists bugs and missing features as known conditions. Developers who want a stable rendering surface should look elsewhere for now. Developers building Rust desktop or mobile applications who want HTML layout and CSS styling as a library, not as a browser, are the intended users.

The project also positions itself against feature creep deliberately. The goals section states that Blitz does not want to support the entirety of browser features, and that any extra features should be opt-in. WebRTC, WebSockets, Bluetooth, and localStorage are named as things Blitz does not provide. The argument in the README is that in a native app, much of that functionality can come from regular Rust crates instead of being coupled to the renderer. That is a coherent design position, and it shapes everything about the architecture.

## How the Modular Crates Fit Together

Blitz is not one crate. The workspace Cargo.toml lists members including blitz-traits, blitz-dom, blitz-html, blitz-net, blitz-paint, blitz-shell, blitz, stylo_taffy, dioxus-native, and dioxus-native-dom, plus apps and examples. The layering is the point.

At the bottom is blitz-traits, described as a minimal base crate containing types and traits so the other crates can interoperate without depending on each other. Above that sits blitz-dom, the core DOM abstraction. It handles style resolution, layout, and event handling, but not parsing, rendering, or system integration. It delegates CSS parsing and resolution to Stylo, box-level layout to Taffy, and text layout to Parley. Those are three separate external projects, and blitz-dom is the crate that binds them.

Parsing is a separate concern. blitz-html adds HTML parsing to blitz-dom using html5ever, with xml5ever for XHTML. Networking is separate again: blitz-net fetches resources over HTTP, from the file system, or from encoded data URIs, using reqwest. Painting is separate: blitz-paint translates a blitz-dom tree into anyrender draw commands. And windowing is separate: blitz-shell integrates a Winit event loop along with AccessKit for accessibility and Muda for system menus.

On top of these pieces sit two high-level wrappers. The blitz crate is an HTML and markdown frontend that renders an HTML string, and the README notes it "currently lacks interactivity." The dioxus-native crate renders a Dioxus VirtualDom and does have full interactivity via Dioxus event handling. Both wrappers can optionally use blitz-net for sub-resources. The README also notes that the anyrender rendering abstraction now lives in its own repository at github.com/dioxuslabs/anyrender, which means the drawing layer is versioned independently of Blitz itself. That is a real integration consideration: a change in anyrender is a change in Blitz's rendering path.

## Running the Browser UI and Markdown Viewer

The README's "Trying it out" section gives two steps: clone the repository, then run one of the examples. There is no published install command for a binary; the path is building from source with Cargo. The workspace edition is 2024 and the declared rust-version is 1.91.0, so a recent Rust toolchain is required.

The first command in the README launches the Browser UI:

```bash
cargo run -rp browser
```

The `-rp` flag is shorthand for `--release --package`. The browser application lives under apps/browser in the workspace. According to the README, runnable builds of this Browser UI are also available on the downloads page for Windows, macOS, Linux, and Android, so building from source is not the only option.

The second documented example is a markdown viewer, which takes a file path as an argument:

```bash
cargo run -rp rdme ./README.md
```

Here `rdme` is the package name for the readme application, and the argument is the file to render. The README also lists a TodoMVC example and a WGPU texture integration example:

```bash
cargo run -rp todomvc
cargo run -rp wgpu_texture
```

The justfile in the repository root wraps many of these with named recipes. For example, `just dev` runs `cargo run --package rdme` with logging features enabled, and `just browser` runs the browser package with `log-frame-times` and `log-phase-times`. There are also backend-specific recipes such as `just cpu`, `just skia`, and `just hybrid`, each selecting a different rendering feature set on the rdme package. If you want to see how the renderer behaves under different backends, those recipes are the shortest route.

## Using the Git Version of Dioxus Native

The README devotes a section to consuming dioxus-native from git rather than from a published release. The stated reason is that Dioxus Native is under rapid development, so the git version can provide features and fixes sooner than an official release. This is a concrete sign of churn, and it comes with a specific migration cost.

The instructions are explicit. Remove your dependency on the dioxus crate entirely. Then add the git dependency with a pinned revision:

```toml
dioxus-native = { git = "https://github.com/DioxusLabs/blitz", rev = "e64a3d8", features = ["prelude"] }
```

The README says to replace `e64a3d8` with the commit id of the version you want. After that, every `use dioxus::prelude::*` in your code must become `use dioxus_native::prelude::*`. If you need functionality from dioxus that the Dioxus Native prelude does not export, the README directs you to import from individual sub-crates such as dioxus-html, dioxus-signals, or dioxus-router instead.

There is one compatibility guarantee worth noting. The git versions of Dioxus Native still depend on the stable v0.7.x version of Dioxus from crates.io, so additional libraries like dioxus-sdk, dioxus-components, and dioxus-free-icons should continue to work. That reduces the blast radius, but it does not remove the need to pin a revision and track it.

## What Blitz Does Not Do, and When That Matters

The most important limitation is stated in the goals section: Blitz does not provide WebRTC, WebSockets, Bluetooth, or localStorage. This is a design decision, not a backlog item, and the README explains the reasoning. In a native app, those capabilities can come from ordinary Rust crates without being coupled to the renderer. If your application is a web page ported to native and it depends on localStorage for state, Blitz will not supply that. You would need to implement the equivalent yourself and wire it into the DOM layer.

JavaScript support is the other boundary. The workspace lists a member called blitz-vibey-script, but the README's status section says Blitz "can already render many popular no-JS websites (Wikipedia, (Old) Reddit, etc)." That phrasing is a scope statement: the engine is measured against sites that do not require scripting. The README also says there are no bindings for JavaScript, Python, or other languages yet, though contributions along those lines would be accepted. If your content is a single-page application, Blitz in its current beta state is the wrong tool.

The two high-level wrappers have different interactivity profiles. The blitz crate renders an HTML string but the README says it "currently lacks interactivity." The dioxus-native crate does have full interactivity through Dioxus event handling. Choosing between them is therefore not just an API preference; it determines whether user input does anything. For a static preview or a markdown viewer, the simpler wrapper is adequate. For an application with buttons and forms, dioxus-native is the path the README describes.

Finally, the beta status itself is a limitation. The README says the project is "actively working on bringing it up to production quality," and points to a status page for current CSS coverage and a roadmap issue for planned work. Those two links are where you should check whether the specific CSS features your content relies on are implemented, rather than assuming broad coverage.

## How Blitz Compares to Servo and Electron

The closest architectural relative is Servo, and the relationship is not distant. Blitz uses Stylo, Servo's CSS engine, for parsing and resolution, and html5ever, also from Servo, for HTML parsing. So the CSS and HTML parsing layers are shared lineage. The difference is the target. Servo is a browser engine project with the goal of rendering the web; Blitz is a rendering library for embedding in a native application, and it deliberately excludes the browser features it considers unnecessary. Blitz also swaps in Taffy for box-level layout rather than using Servo's own layout system, and Parley for text. If you want a browser, Servo is the project with that ambition. If you want a renderer as a component, Blitz is the one that makes that trade.

The other comparison is Electron and similar webview-based approaches. Those bundle a full browser runtime and give you JavaScript, localStorage, and the rest of the web platform. The cost is the runtime itself, which is what the Blitz README is reacting to when it calls the browser bloated for basic HTML/CSS rendering. The trade is direct: Electron gives you the whole platform and its weight; Blitz gives you layout and painting in Rust and asks you to supply anything else you need. Neither is strictly better. If your application is already a web application, Electron or a system webview is the shorter path. If your application is a Rust program that needs to render some HTML, Blitz avoids embedding a second runtime.

A third point of comparison is anyrender, the 2D drawing abstraction that blitz-paint targets. Because anyrender lives in its own repository, Blitz's rendering backend is decoupled from the engine. That means the choice of drawing layer is somewhat open, which is different from engines that hard-code their graphics stack. The README does not enumerate the available anyrender backends, so that is something to check in the anyrender repository rather than in Blitz's documentation.

## Licence and Upgrade Considerations

The repository root contains LICENSE-APACHE and LICENSE-MIT, and the README states the project is dual licensed under Apache 2.0 and MIT. The workspace Cargo.toml declares `license = "MIT OR Apache-2.0"`, which matches. There is one exception worth flagging: the README says the stylo_taffy crate is additionally licensed under MPL 2.0, making it triple licensed under Apache 2.0, MIT, and MPL 2.0. That crate is a workspace member, so if your dependency graph pulls it in, the MPL terms apply to that component. This is a factual description of the licence files, not legal advice; if your organisation has policies about MPL-licensed dependencies, that is the crate to examine.

On upgrade cost, the version string in the workspace is 0.3.0-beta.2, and the internal dependencies are pinned with exact equality, for example `blitz-dom = { version = "=0.3.0-beta.2", ... }`. Exact pinning across a workspace of this size means the crates move together; you cannot mix a beta.1 blitz-dom with a beta.2 blitz-shell. For consumers, that is simpler in one sense and stricter in another.

The git-based dioxus-native workflow adds its own upgrade burden. Because the README instructs you to pin a specific revision, upgrading means changing that revision and re-running your build, and the import rewrite from `dioxus::prelude` to `dioxus_native::prelude` means your code is coupled to the prelude's contents. The README notes that git versions still depend on stable Dioxus v0.7.x from crates.io, which limits how far the ecosystem around it can drift, but it does not eliminate the need to test after each revision bump. The repository has no retrieved release notes, so version-to-version changes should be read from the commit history and the roadmap issue rather than from a changelog.

## Conclusion

Adopt Blitz if you are building a Rust native application and need to render HTML or CSS without a browser engine, and you accept beta-level API churn. Do not adopt it if you need JavaScript execution, WebRTC, WebSockets, or localStorage, because the README states these are explicitly out of scope. Before committing, verify the current WPT status page for the CSS features your content depends on, and check whether the git revision of dioxus-native you pin still matches the crates.io release of Dioxus v0.7.x.

## FAQ

### How do I install Blitz?

There is no published install command in the README. The documented path is to clone the repository and run one of the examples with Cargo, for example `cargo run -rp browser` for the Browser UI. Runnable builds of the Browser UI are also offered on the downloads page for Windows, macOS, Linux, and Android.

### How do I use Blitz?

The README gives several example commands to run from a clone of the repository, including `cargo run -rp browser` for the Browser UI, `cargo run -rp rdme ./README.md` for the markdown viewer, and `cargo run -rp todomvc` for the TodoMVC app. For application development, the two high-level wrappers are the blitz crate for rendering an HTML string and dioxus-native for rendering a Dioxus VirtualDom with interactivity.

### Does Blitz run JavaScript?

The README's status section describes Blitz as able to render many popular no-JS websites, and the goals section states that Blitz does not intend to support the entirety of browser features. WebRTC, WebSockets, Bluetooth, and localStorage are named as features Blitz does not provide. There are no bindings for JavaScript, Python, or other languages yet.

### What licence is Blitz under?

The README states the project is dual licensed under Apache 2.0 and MIT, and the repository contains LICENSE-APACHE and LICENSE-MIT. The stylo_taffy crate is additionally licensed under MPL 2.0, making it triple licensed under Apache 2.0, MIT, and MPL 2.0.

### Can I use Blitz with Dioxus from git?

Yes. The README describes removing your dependency on the dioxus crate, adding dioxus-native as a git dependency with a pinned revision and the prelude feature, and changing `use dioxus::prelude::*` to `use dioxus_native::prelude::*`. The git versions still depend on the stable v0.7.x version of Dioxus from crates.io.

## Sources

- [DioxusLabs/blitz on GitHub](https://github.com/DioxusLabs/blitz)
- [Issues](https://github.com/DioxusLabs/blitz/issues)
- [License: Apache-2.0](https://github.com/DioxusLabs/blitz/blob/main/LICENSE)
- [Project website](https://blitz.is)
- [README](https://github.com/DioxusLabs/blitz/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dioxuslabs-blitz
