Leptos is a Rust web framework with fine-grained reactivity (like SolidJS) and built-in SSR. Write your frontend AND backend in Rust, compile to WebAssembly for the client, and native binary for the server.
Why Leptos?
- Fine-grained reactivity — only updates what changed (like Solid, not React)
- Full-stack Rust — one language, one codebase, frontend + backend
- Blazing fast — Rust → WASM, smallest bundle sizes
- Server functions — call backend code like regular functions
- SSR + hydration — SEO-ready out of the box
Quick Start
# Install cargo-leptos
cargo install cargo-leptos
# Create new project
cargo leptos new my-app
cd my-app
# Dev server with hot reload
cargo leptos watch
# App at http://localhost:3000
Components (Fine-Grained Reactivity)
use leptos::*;
#[component]
fn Counter() -> impl IntoView {
let (count, set_count) = signal(0);
view! {
<div>
<h1>"Counter: " {count}</h1>
<button on:click=move |_| set_count.update(|n| *n += 1)>
"Click me"
</button>
</div>
}
}
#[component]
fn App() -> impl IntoView {
view! {
<main>
<h1>"My Leptos App"</h1>
<Counter />
</main>
}
}
Server Functions (Full-Stack Magic)
// This runs on the SERVER but is callable from the CLIENT
#[server(GetUsers)]
pub async fn get_users() -> Result<Vec<User>, ServerFnError> {
// Server-side code: database queries, file system, etc.
let users = sqlx::query_as::<_, User>("SELECT * FROM users")
.fetch_all(&pool())
.await?;
Ok(users)
}
// This component calls the server function
#[component]
fn UserList() -> impl IntoView {
let users = Resource::new(|| (), |_| get_users());
view! {
<Suspense fallback=|| view! { <p>"Loading..."</p> }>
{move || users.get().map(|result| match result {
Ok(users) => users.iter().map(|user| {
view! { <p>{&user.name}</p> }
}).collect_view(),
Err(e) => view! { <p>"Error: " {e.to_string()}</p> }.into_any(),
})}
</Suspense>
}
}
Routing
use leptos_router::*;
#[component]
fn App() -> impl IntoView {
view! {
<Router>
<nav>
<a href="/">"Home"</a>
<a href="/about">"About"</a>
<a href="/users">"Users"</a>
</nav>
<main>
<Routes>
<Route path="/" view=HomePage />
<Route path="/about" view=AboutPage />
<Route path="/users" view=UserList />
<Route path="/users/:id" view=UserDetail />
</Routes>
</main>
</Router>
}
}
#[component]
fn UserDetail() -> impl IntoView {
let params = use_params_map();
let id = move || params.get().get("id").unwrap_or_default();
view! { <h1>"User: " {id}</h1> }
}
Performance Comparison
| Framework | Bundle Size | TTI |
|---|---|---|
| Leptos | ~30 KB | ~0.5s |
| SolidJS | ~7 KB | ~0.6s |
| React | ~130 KB | ~1.2s |
| Next.js | ~200 KB | ~1.5s |
Resources
Building high-performance web apps? I create custom tools and automation. Check my Apify actors or email spinov001@gmail.com.
Top comments (0)