Skip to content
STACK IT FAST

Leptos Full-Stack Rust (SSR + Hydration on Axum)

Curated rule SaaS / Web App · Internal Admin Tool · Developer Tool & API Updated Oct 2026 Which file does my tool read?
rust-leptos-fullstack.md

Full-stack Rust web app rules: Leptos 0.8 SSR with hydration, server functions on Axum, sqlx + PostgreSQL, cargo-leptos and Tailwind, written for AI agents.

Formats
4 files
AGENTS.md
50 lines
CLAUDE.md
17 lines
Languages
Rust
Updated
Oct 2026
Used by
4 projects
Install

Writes .claude/skills/rust-leptos-fullstack/SKILL.md

$ curl -s --create-dirs -o .claude/skills/rust-leptos-fullstack/SKILL.md https://stackitfast.com/rules/rust-leptos-fullstack/SKILL.md

Rule files

AGENTS.md· 50 lines · 3.9 KB
1# Project Architecture & Guidelines (Leptos Full-Stack Rust)
2
3## 1. System Architecture
4- **Framework**: Leptos 0.8 with server-side rendering and hydration (`ssr` and `hydrate` features), served by Axum through `leptos_axum`.
5- **Build tool**: `cargo-leptos` builds the server binary and the WASM client bundle together and serves `cargo leptos watch` with live reload.
6- **Data**: PostgreSQL via `sqlx` 0.9, used only inside server-only code.
7- **Styling**: Tailwind CSS (configured through cargo-leptos `tailwind-input-file`).
8- **Toolchain**: Rust 2024 edition, pinned in `rust-toolchain.toml`, with the `wasm32-unknown-unknown` target installed.
9
10## 2. Project Layout
11- `src/app.rs`: `App` component, `<Router>` and `<Routes>`, the HTML `shell` function.
12- `src/pages/<route>.rs`: one module per route; components only.
13- `src/api/<feature>.rs`: `#[server]` functions for that feature, the only place that touches the database.
14- `src/server/`: `#[cfg(feature = "ssr")]` modules (pool setup, auth, repositories). Never imported by client code.
15- `src/main.rs`: Axum router with `leptos_routes_with_context`, providing the `PgPool` through context.
16- `src/lib.rs`: the `hydrate()` entry point for the WASM bundle.
17- `style/`, `public/`, `migrations/`, `end2end/` (Playwright).
18
19## 3. Components and Reactivity
20- Components are `#[component] fn Name(...) -> impl IntoView` with `view! {}`; keep them small and named after what they render.
21- State with `signal()`, derived values with `Memo` or plain closures; never duplicate state that can be derived.
22- Load data with `Resource::new(source, fetcher)` (serialised from server to client during hydration) and render it inside `<Suspense>` or `<Transition>`. Use `LocalResource` only for browser-only data.
23- Mutations go through `ServerAction::<Fn>::new()` and `<ActionForm>`, so forms work before WASM loads (progressive enhancement).
24- Avoid `create_effect`-style effects for data flow; reach for resources and actions first.
25
26## 4. Server Functions (the API boundary)
27- Every server function is `#[server] pub async fn name(args) -> Result<T, ServerFnError>` in `src/api/`.
28- Get shared state with `use_context::<PgPool>()` (provided in `leptos_routes_with_context`), never a global.
29- Validate and authorise inside the server function; it is a public HTTP endpoint even if only your UI calls it.
30- Return domain structs that derive `Serialize`, `Deserialize`, `Clone`; never return `sqlx` rows or secrets.
31- Server-only crates (`sqlx`, `argon2`, `tower-sessions`) are `optional = true` and enabled only by the `ssr` feature.
32
33## 5. Feature Gating Rules
34- Code that touches the database, filesystem or secrets lives behind `#[cfg(feature = "ssr")]`.
35- Code that touches `web_sys`/`window` runs only in effects or behind `#[cfg(feature = "hydrate")]`.
36- Hydration mismatches come from rendering different markup on server and client (random IDs, `Utc::now()`, browser-only checks); compute such values on the server and pass them down.
37
38## 6. Agent Loop (run after every change)
391. `cargo check --features ssr` and `cargo check --features hydrate --target wasm32-unknown-unknown`; both must be clean.
402. `cargo clippy --features ssr -- -D warnings`.
413. `cargo test --features ssr`.
424. For UI changes, `cargo leptos end-to-end` (Playwright) or load the page and check the browser console for hydration warnings.
43- Do not fix borrow errors in closures by sprinkling `.clone()` on large values; move `Copy` signals into closures instead (signals are `Copy` in 0.8).
44- No `unwrap()` in server functions; map errors into `ServerFnError`.
45
46## 7. Testing and CI
47- Unit-test pure logic and server-only repositories with `#[sqlx::test]`.
48- Playwright tests in `end2end/` cover each route with JavaScript disabled once (ActionForm must still work) and enabled once.
49- CI: `cargo fmt --check`, both `cargo check` targets, clippy, tests, `cargo leptos build --release`.
50- Deploy the server binary plus the `target/site/` directory; set `LEPTOS_SITE_ADDR` and `LEPTOS_SITE_ROOT` in the environment.

Works with Claude Code · Cursor · Windsurf · AGY

Architecture notes

Architecture Overview

One language end to end. Leptos renders components on the server for fast first paint and SEO, hydrates them in the browser as WebAssembly, and calls typed #[server] functions instead of a hand-written REST API. Axum hosts it, sqlx talks to PostgreSQL, and cargo-leptos builds both halves.

Why it suits AI coding agents

  • The client-server contract is a Rust function signature. Change a server function’s return type and every call site in the UI fails to compile, so an agent cannot ship a frontend and backend that disagree.
  • Feature gates make boundaries explicit. Database code behind ssr cannot leak into the browser bundle without a compile error.
  • Progressive enhancement by default. ActionForm posts work before the WASM loads, which keeps end-to-end tests simple.

Trade-offs

Two compile targets mean slower loops than the Axum + htmx stack, WASM bundles add weight, and the component ecosystem is young. Start with htmx unless the UI genuinely needs client-side state. Background: Building web apps in Rust in 2026.

Frequently asked questions

Is Leptos production-ready in 2026?

Leptos 0.8 is stable and actively maintained, with SSR, hydration, server functions and an Axum integration. Its ecosystem is much smaller than React's, so expect to write more components yourself; none of the open-source Rust apps in the STACK IT FAST directory ships a Leptos UI yet.

Leptos or Dioxus?

Pick Leptos for web apps that need server-side rendering and SEO, because SSR, hydration and server functions are its core design. Pick Dioxus when the same Rust UI code has to run on desktop and mobile as well as the web.

Why does the agent need to check two targets?

A Leptos app compiles twice: once for the server with the ssr feature and once to WebAssembly with the hydrate feature. Code that compiles for the server can still break the WASM build (for example by importing sqlx), so cargo check must pass for both before a change is done.

Do I still need a separate API?

Not for your own UI. Server functions are typed RPC endpoints generated from Rust functions, so the client calls them like async functions. Add a separate Axum JSON API only when third parties or mobile apps need a stable public contract.

Used in production

Explore all stacks