# Leptos: fine-grained reactivity in Rust for full-stack web apps

> Leptos is an MIT-licensed Rust web framework that renders on the server or in the browser from the same components. The 0.8 line is stable, 0.9 is still in beta, and the workspace pins Rust 1.88.

**leptos-rs/leptos** — Build fast web applications with Rust.

- Repository: https://github.com/leptos-rs/leptos
- Website: https://leptos.dev
- Stars: 21,342 · Forks: 902
- Language: Rust
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/leptos-rs-leptos

## The problem Leptos solves for Rust teams

Rust has a mature server story and a thin browser story. Writing a web application usually means picking one: an Axum or Actix service that returns JSON, plus a JavaScript front end that owns all the interaction. Leptos targets the gap between those two halves. The README describes it as a "full-stack, isomorphic Rust web framework" and the repository is laid out to match, with server_fn, server_fn_macro, hydration_context and leptos_server as separate workspace members alongside the view layer.

That layout tells you who the framework is for. The audience is a team that already compiles Rust on the server and does not want to maintain a second language, a second dependency tree and a hand-written HTTP contract for every screen. The counterpart is a team with a large JavaScript codebase and no Rust on the server. For them Leptos adds a toolchain without removing anything, and the trade is not worth making.

The repository also excludes examples, benchmarks and projects from the workspace, so the published crates are the framework and its integrations, not the sample apps. That is a deliberate split: consuming Leptos does not pull in the demo code.

## How fine-grained reactivity and server functions fit together

The mechanism is a reactive graph, not a virtual DOM. The README states that when a signal's value changes it can update a single text node, toggle a single class, or remove an element from the DOM with no other code running, and it names the absence of virtual DOM overhead as the reason. The reactive_graph, reactive_stores and reactive_stores_macro crates in the workspace are where that machinery lives, separate from the rendering crate tachys.

The README's counter example shows the shape of the API. A call to signal returns a getter and a setter, both Copy, so they move into closures without cloning. Handlers call set_value directly or set_value.update with a closure. The view! macro expands into a builder API, and the README shows both forms side by side, including a div().child((...)) chain using leptos::html, which is useful when you want to see what the macro produces.

On the server side, the isomorphic claim rests on server functions. The README says these are functions with the same shape on client and server that only run on the server, so database access and authentication sit next to the components that consume them. That removes the separate REST layer, and it also means the client bundle carries the call site, not the implementation. Rendering is not limited to one mode: the README lists client-side rendering, server-side rendering, and SSR with hydration, plus HTTP streaming of data through Resource and of HTML through Suspense components, in either out-of-order or in-order form.

## Installing cargo-leptos and running a first app

The README points at cargo-leptos as the build tool for apps that run on both client and server, and pairs it with starter templates for Actix and Axum. Install the tool first. The --locked flag is in the README's own command.

```bash
cargo install cargo-leptos --locked
```

Then generate a project from the Axum starter. The README uses --git with the repository URL, and the generated directory is named after the project, which is why the next line changes into a placeholder.

```bash
cargo leptos new --git https://github.com/leptos-rs/start-axum
cd [your project name]
cargo leptos watch
```

cargo leptos watch is the development loop: it builds the client and server targets and serves the app, so you should see the starter's page in a browser rather than a compiled binary you have to launch yourself. If you write your own rand or getrandom code, the README warns that Leptos configures its own wasm randomness but not your dependencies'. You have to enable the JavaScript backend in your own manifest, and the README gives this example:

```toml
[dependencies]
# Make sure getrandom works on wasm by enabling its JS backend
getrandom = { version = "0.2", features = ["js"] }
rand      = { version = "0.8", features = ["small_rng"] }
```

Without that backend the README says the build can fail or randomness will not work in the browser. The examples js-framework-benchmark and hackernews_js_fetch already do this and are the reference to copy.

## Where Leptos gets in your way

The book is labeled "work in progress" in the README's own list of learning resources. That is the honest state of the documentation, and it means the examples directory and the API docs on docs.rs carry more weight than a tutorial would. A team that expects a finished guide will spend its first week reading source and examples.

The version story is the second constraint. The workspace manifest declares leptos 0.8.20, leptos_router 0.8.15 and leptos_macro 0.8.17, while the most recent release tag is v0.9.0-beta from 2026-07-18, preceded by v0.9.0-alpha and v0.8.19. So the stable line and the beta line are both in the repository at once, and anything built on 0.9 is built on a beta. The README does not document an upgrade path between them.

The toolchain is the third. The workspace sets rust-version to 1.88 and edition to 2021. A pinned CI image older than that will fail before any Leptos code is compiled, and because the framework splits across roughly two dozen crates, a version skew between leptos, leptos_macro and server_fn surfaces as macro errors rather than a clean dependency conflict. A plain cargo build also does not produce a working browser app on its own; the README routes you through cargo-leptos or a wasm-bindgen setup, and that distinction catches people who expect a single build command.

## Leptos compared with Yew and Dioxus

Both Yew and Dioxus are Rust front-end frameworks, and the difference from Leptos is the rendering model. Yew follows a component-and-virtual-DOM design closer to React: components re-render and the diff decides what reaches the DOM. Leptos skips the diff. Its signals update the specific node or class they are bound to, which is why the README can claim minimal overhead and no virtual DOM. The cost is that you think in terms of signals and their dependencies rather than in terms of a component re-running.

Dioxus is the closer comparison in scope, since it also targets desktop and other platforms beyond the browser. Leptos stays on the Web platform by design. The README says the router is built on Web fundamentals like links and forms rather than replacing them, and the topics list is dom, isomorphic, ssr and webassembly. If your target is a browser application with a server behind it, that focus is a benefit. If you need one codebase for desktop and mobile as well, the narrower scope is a limitation, not a feature.

The repository also ships an islands example and a hackernews_islands_axum example, so partial hydration is part of the framework rather than an add-on. That is the option to look at when you want server-rendered HTML with interactivity in a few places instead of a fully hydrated app.

## Maintenance, licensing and the cost of upgrading

The repository is not archived, and the last push was on 2026-09-18. Releases arrive on a short cadence: v0.9.0-alpha on 2026-05-19, v0.8.19 on 2026-06-25 and v0.9.0-beta on 2026-07-18. That rhythm is good for fixes and awkward for stability, because the workspace still points at 0.8.20 while 0.9 is in beta. Plan on reading release notes before each bump rather than assuming a patch release is inert.

The licence is MIT, declared at the repository root. MIT permits commercial use and modification and requires that the copyright notice and permission notice be included in copies or substantial portions. That is a permissive arrangement, and the practical obligation is attribution in distributed artifacts. It also means no contributor licence agreement grants you patent protection the way an Apache-2.0 grant would; if your legal review cares about that distinction, it is worth raising. This is a description of the licence text, not legal advice.

The upgrade cost is structural. A Leptos application depends on the framework crate, the macro crate, the router, server_fn and one integration crate, and the workspace versions them independently. When you bump one, check the others, because a mismatch between the view macro and the runtime is the failure mode you are most likely to hit.

## Conclusion

Adopt Leptos if your team already writes Rust and wants server functions and signals without a separate REST layer, and start from the Axum or Actix starter rather than an empty crate. Do not adopt it if you need a finished book, an API frozen across minor versions, or a framework where a plain cargo build produces a working browser app. Before committing, check the workspace rust-version of 1.88 against your toolchain, and decide whether you are willing to track the 0.9 beta line, because the workspace declares leptos 0.8.20 while the newest published tag is v0.9.0-beta.

## FAQ

### What is Leptos in Rust?

Leptos is a full-stack, isomorphic Rust web framework that uses fine-grained reactivity to build declarative user interfaces. The README says it can render in the browser, on the server, or on the server with hydration in the browser.

### Which is better, Dioxus or Leptos?

The documentation does not rank them. The concrete difference is scope: Leptos is built on the Web platform and its router uses Web fundamentals like links and forms, while its rendering model updates individual DOM nodes through signals instead of a virtual DOM.

### How do I install Leptos?

The README's route is cargo install cargo-leptos --locked, then cargo leptos new --git with the Axum or Actix starter repository, followed by cargo leptos watch in the generated project. The workspace requires Rust 1.88.

### Does Leptos use a virtual DOM?

No. The README states that when a signal's value changes it can update a single text node, toggle a single class, or remove an element from the DOM without other code running, and it names the absence of virtual DOM overhead as the result.

### What licence does Leptos use?

MIT, declared at the repository root. That permits commercial use and modification provided the copyright and permission notices are included in copies or substantial portions.

## Sources

- [leptos-rs/leptos on GitHub](https://github.com/leptos-rs/leptos)
- [License: MIT](https://github.com/leptos-rs/leptos/blob/main/LICENSE)
- [Project website](https://leptos.dev)
- [README](https://github.com/leptos-rs/leptos/blob/main/README.md)
- [Releases](https://github.com/leptos-rs/leptos/releases)

---

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