leptos Documentation

Build fast web applications with Rust.

21,395 stars Rust Rust 187 files Β· ~37,815 tokens #dom#fine-grained#isomorphic#reactive#rust#ssr#web#webassembly
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy leptos on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name leptos -p 1080:1080 --restart always marlonb/mailcrab:latest
Configured Services & Ports
βš™οΈ mailcrab
image: marlonb/mailcrab:latest
πŸ”Œ Ports: 1080:1080, 1025:1025
βš™οΈ kratos
image: oryd/kratos:v1.1.0
πŸ”Œ Ports: 4433:4433, 4434:4434
docker-compose.yml
yaml (docker-compose.yml)
version: '3.7'
services:
  mailcrab:
    image: marlonb/mailcrab:latest
    ports:
      - "1080:1080"
      - "1025:1025"
    networks:
      - mynetwork

  kratos:
    image: oryd/kratos:v1.1.0
    command: serve --dev --config /etc/config/kratos/kratos.yaml --watch-courier
    volumes:
      - "./kratos:/etc/config/kratos"
    ports:
      - "4433:4433"
      - "4434:4434"
    networks:
      - mynetwork
  
networks:
  mynetwork:
    driver: bridge

Technical Documentation: leptos-rs/leptos

ℹ️ Provenance: Multi-Tier Ingestion Β· CodeWiki Reference

Overview (`README.md`)



Website | Book | Docs.rs | Playground | Discord

You can find a list of useful libraries and example projects at awesome-leptos.

Leptos

text
/* Detailed source-code truncated for AI context efficiency. */

About the Framework

Leptos is a full-stack, isomorphic Rust web framework leveraging fine-grained reactivity to build declarative user interfaces.

What does that mean?

  • Full-stack: Leptos can be used to build apps that run in the browser (client-side rendering), on the server (server-side rendering), or by rendering HTML on the server and then adding interactivity in the browser (server-side rendering with hydration). This includes support for HTTP streaming of both data (Resources) and HTML (out-of-order or in-order streaming of <Suspense/> components.)
  • Isomorphic: Leptos provides primitives to write isomorphic server functions, i.e., functions that can be called with the β€œsame shape” on the client or server, but only run on the server. This means you can write your server-only logic (database requests, authentication etc.) alongside the client-side components that will consume it, and call server functions as if they were running in the browser, without needing to create and maintain a separate REST or other API.
  • Web: Leptos is built on the Web platform and Web standards. The router is designed to use Web fundamentals (like links and forms) and build on top of them rather than trying to replace them.
  • Framework: Leptos provides most of what you need to build a modern web app: a reactive system, templating library, and a router that works on both the server and client side.
  • Fine-grained reactivity: The entire framework is built from reactive primitives. This allows for extremely performant code with minimal overhead: when a reactive signal’s value changes, it can update a single text node, toggle a single class, or remove an element from the DOM without any other code running. (So, no virtual DOM overhead!)
  • Declarative: Tell Leptos how you want the page to look, and let the framework tell the browser how to do it.

Learn more

Here are some resources for learning more about Leptos:

Random numbers on wasm (`rand` / `getrandom`)

When you compile a Leptos app to wasm32-unknown-unknown, rand and getrandom need a JavaScript-backed source of randomness. If that backend isn’t enabled, your build can fail or randomness just won’t work in the browser.

Leptos itself takes care of this for its own code, but that does not automatically configure your app’s own rand / getrandom dependencies. If you use them directly, you need to turn on the JS backend yourself.

A simple setup in your Cargo.toml might look like this:

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"] }

Some of the examples in this repo (for example js-framework-benchmark and hackernews_js_fetch) already do this, so you can use them as a reference if you’re unsure.

`cargo-leptos`

cargo-leptos is a build tool that's designed to make it easy to build apps that run on both the client and the server, with seamless integration. The best way to get started with a real Leptos project right now is to use cargo-leptos and our starter templates for Actix or Axum.

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

Open browser to http://localhost:3000/.

FAQs

What’s up with the name?

Leptos (Ξ»Ξ΅Ο€Ο„ΟŒΟ‚) is an ancient Greek word meaning β€œthin, light, refined, fine-grained.” To me, a classicist and not a dog owner, it evokes the lightweight reactive system that powers the framework. I've since learned the same word is at the root of the medical term β€œleptospirosis,” a blood infection that affects humans and animals... My bad. No dogs were harmed in the creation of this framework.

Is it production ready?

People usually mean one of three things by this question.

  1. Are the APIs stable? i.e., will I have to rewrite my whole app from Leptos 0.1 to 0.2 to 0.3 to 0.4, or can I write it now and benefit from new features and updates as new versions come?

The APIs are basically settled. We’re adding new features, but we’re very happy with where the type system and patterns have landed. I would not expect major breaking changes to your code to adapt to future releases, in terms of architecture.

  1. Are there bugs?

Yes, I’m sure there are. You can see from the state of our issue tracker over time that there aren’t that many bugs and they’re usually resolved pretty quickly. But for sure, there may be moments where you encounter something that requires a fix at the framework level, which may not be immediately resolved.

  1. Am I a consumer or a contributor?

This may be the big one: β€œproduction ready” implies a certain orientation to a library: that you can basically use it, without any special knowledge of its internals or ability to contribute. Everyone has this at some level in their stack: for example I (@gbj) don’t have the capacity or knowledge to contribute to something like wasm-bindgen at this point: I simply rely on it to work.

There are several people in the community using Leptos right now for many websites at work, who have also become significant contributors. There may be missing features that you need, and you may end up building them! But, if you're willing to contribute a few missing pieces along the way, the framework is most definitely usable for production applications, especially given the ecosystem of libraries that have sprung up around it.

Can I use this for native GUI?

Sure! Obviously the view macro is for generating DOM nodes but you can use the reactive system to drive any native GUI toolkit that uses the same kind of object-oriented, event-callback-based framework as the DOM pretty easily. The principles are the same:

  • Use signals, derived signals, and memos to create your reactive system
  • Create GUI widgets
  • Use event listeners to update signals
  • Create effects to update the UI

The 0.7 update originally set out to create a "generic rendering" approach that would allow us to reuse most of the same view logic to do all of the above. Unfortunately, this has had to be shelved for now due to difficulties encountered by the Rust compiler when building larger-scale applications with the number of generics spread throughout the codebase that this required. It's an approach I'm looking forward to exploring again in the future; feel free to reach out if you're interested in this kind of work.

How is this different from Yew?

Yew is the most-used library for Rust web UI development, but there are several differences between Yew and Leptos, in philosophy, approach, and performance.

  • VDOM vs. fine-grained: Yew is built on the virtual DOM (VDOM) model: state changes cause components to re-render, generating a new virtual DOM tree. Yew diffs this against the previous VDOM, and applies those patches to the actual DOM. Component functions rerun whenever state changes. Leptos takes an entirely different approach. Components run once, creating (and returning) actual DOM nodes and setting up a reactive system to update those DOM nodes.
  • Performance: This has huge performance implications: Leptos is simply much faster at both creating and updating the UI than Yew is.
  • Server integration: Yew was created in an era in which browser-rendered single-page apps (SPAs) were the dominant paradigm. While Leptos supports client-side rendering, it also focuses on integrating with the server side of your application via server functions and multiple modes of serving HTML, including out-of-order streaming.

How is this different from Dioxus?

Like Leptos, Dioxus is a framework for building UIs using web technologies. However, there are significant differences in approach and features.

  • VDOM vs. fine-grained: While Dioxus has a performant virtual DOM (VDOM), it still uses coarse-grained/component-scoped reactivity: changing a stateful value reruns the component function and diffs the old UI against the new one. Leptos components use a different mental model, creating (and returning) actual DOM nodes and setting up a reactive system to update those DOM nodes.
  • Web vs. desktop priorities: Dioxus uses Leptos server functions in its fullstack mode, but does not have the same <Suspense>-based support for things like streaming HTML rendering, or share the same focus on holistic web performance. Leptos tends to prioritize holistic web performance (streaming HTML rendering, smaller WASM binary sizes, etc.), whereas Dioxus has an unparalleled experience when building desktop apps, because your application logic runs as a native Rust binary.

How is this different from Sycamore?

Sycamore and Leptos are both heavily influenced by SolidJS. At this point, Leptos has a larger community and ecosystem and is more actively developed. Other differences:

  • Templating DSLs: Sycamore uses a custom templating language for its views, while Leptos uses a JSX-like template format.
  • 'static signals: One of Leptos’s main innovations was the creation of Copy + 'static signals, which have excellent ergonomics. Sycamore is in the process of adopting the same pattern, but this is not yet released.
  • Perseus vs. server functions: The Perseus metaframework provides an opinionated way to build Sycamore apps that include server functionality. Leptos instead provides primitives like server functions in the core of the framework.

Overview (`any_error/README.md`)

A utility library for wrapping arbitrary errors, and for β€œthrowing” errors in a way
that can be caught by user-defined error hooks.


Overview (`any_spawner/README.md`)

This crate makes it easier to write asynchronous code that is executor-agnostic, by providing a
utility that can be used to spawn tasks in a variety of executors.

It only supports single executor per program, but that executor can be set at runtime, anywhere
in your crate (or an application that depends on it).

This can be extended to support any executor or runtime that supports spawning [Future]s.

This is a least common denominator implementation in many ways. Limitations include:

  • setting an executor is a one-time, global action
  • no "join handle" or other result is returned from the spawn
  • the Future must output ()
rust
use any_spawner::Executor;

Executor::init_futures_executor()
    .expect("executor should only be initialized once");

// spawn a thread-safe Future
Executor::spawn(async { /* ... */ });

// spawn a Future that is !Send
Executor::spawn_local(async { /* ... */ });

Overview (`either_of/README.md`)

Utilities for working with enumerated types that contain one of 2..n other types.


Overview (`examples/README.md`)

Examples README

Main Branch

The examples in this directory are all built and tested against the current main branch.

To the extent that new features have been released or breaking changes have been made since the previous release, the examples are compatible with the main branch and not the current release.

Getting Started

The simplest way to get started with any example is to use the β€œquick start” command found in the README for each example. Most of the examples use either trunk (a simple build system and dev server for client-side-rendered apps) or cargo-leptos (a build system for server-rendered and client-hydrated apps).

Using Cargo Make

You can also run any of the examples using cargo-make. Note that this is completely optional. We use it for CI, and it can be convenient for running the examples, but is not required.

Follow these steps to get any example up and running.

  1. cd to the example you want to run
  2. Make sure cargo-make is installed (for example by running cargo install cargo-make)
  3. Make sure rustup target add wasm32-unknown-unknown was executed for the currently selected toolchain.
  4. Run cargo make ci to setup and test the example
  5. Run cargo make start to run the example
  6. Open the client URL in the console output (http://127.0.0.1:8080 or http://127.0.0.1:3000 by default)
  7. Run cargo make stop to end any processes started by cargo make start.

Here are a few additional notes:

  • Extendable custom task files are located in the cargo-make directory
  • Running a task will automatically install cargo dependencies
  • Each Makefile.toml file must extend the cargo-make/main.toml file
  • cargo-make files that end in *-test.toml configure web testing strategies
  • Run cargo make test-report to learn which examples have web tests

Prerequisites

Example projects depend on the following tools. Please install them as needed.

  • Rust
  • Nightly Rust
    • Run rustup toolchain install nightly
    • Run rustup target add wasm32-unknown-unknown
  • Cargo Make
    • Run cargo install --force cargo-make
    • Setup a command alias like alias cm='cargo make' to reduce typing (Optional)
  • Trunk
    • Run cargo install trunk
  • Node Version Manager (Optional)
  • Node.js
  • pnpm (Optional)

Overview (`hydration_context/README.md`)

Isomorphic web applications that run on the server to render HTML, then add interactivity in
the client, need to accomplish two tasks:

  1. Send HTML from the server, so that the client can "hydrate" it in the browser by adding
    event listeners and setting up other interactivity.
  2. Send data that was loaded on the server to the client, so that the client "hydrates" with
    the same data with which the server rendered HTML.

This crate helps with the second part of this process. It provides a [SharedContext] type
that allows you to store data on the server, and then extract the same data in the client.


Overview (`next_tuple/README.md`)

Allows extending a tuple, or creating a new tuple, by adding the next value.


Overview (`oco/README.md`)

This module contains the Oco (Owned Clones Once) smart pointer,
which is used to store immutable references to values.
This is useful for storing, for example, strings.

Imagine this as an alternative to [Cow] with an additional, reference-counted
branch.

rust
use oco_ref::Oco;
use std::sync::Arc;

let static_str = "foo";
let arc_str: Arc<str> = "bar".into();
let owned_str: String = "baz".into();

fn uses_oco(value: impl Into<Oco<'static, str>>) {
    let mut value = value.into();

    // ensures that the value is either a reference, or reference-counted
    // O(n) at worst
    let clone1 = value.clone_inplace();

    // these subsequent clones are O(1)
    let clone2 = value.clone();
    let clone3 = value.clone();
}

uses_oco(static_str);
uses_oco(arc_str);
uses_oco(owned_str);

Overview (`or_poisoned/README.md`)

Provides a simple trait that unwraps the locks provide by [std::sync::RwLock].

In every case, this is the same as calling .expect("lock poisoned"). However, it
does not use .unwrap() or .expect(), which makes it easier to distinguish from
other forms of unwrapping when reading code.

rust
use or_poisoned::OrPoisoned;
use std::sync::RwLock;

let lock = RwLock::new(String::from("Hello!"));

let read = lock.read().or_poisoned();
// this is identical to
let read = lock.read().unwrap();

Overview (`projects/README.md`)

`projects` README

The projects directory is intended as a collective of medium-to-large-scale examples: a place to show a variety of use cases and integrations between Leptos and other libraries. Over time, our hope is that this allows us to showcase a wider variety of user examples, without the main examples directory becoming too overwhelming to be useful.

The examples directory is included in our CI, and examples are regularly linted and tested. The barrier to entry for the projects directory is intended to be lower: Example projects will generally be built against a particular version, and not regularly linted or updated. Hopefully this distinction allows us to accept more examples without worrying about the maintenance burden of constant updates.

Feel free to submit projects to this directory via PR!

Index

Meilisearch is a search engine built in Rust that you can self-host. This example shows how to run it alongside a leptos server and present a search bar with autocomplete to the user.

nginx-mpmc

Nginx Multiple Producer Multi Consumer, this example shows how you can use Nginx to provide different clients to the user while running multiple Leptos servers that provide server functions to any of the clients.

ory-kratos

Ory is a combination of different authorization services. Ory Kratos is their Identification service, which provides password storage, emailing, login and registration functionality, etc. This example shows running Ory Kratos alongside a leptos server and making use of their UI Node data types in leptos. TODO: This example needs a bit more work to show off SSO passwordless etc

tauri-from-scratch

This example walks you through in explicit detail how to use Tauri to render your Leptos App on non web targets using WebView while communicating with your leptos server and servering an SSR supported web experience. TODO: It could be simplified since part of the readme includes copying and pasting boilerplate.

counter_dwarf_debug

This example shows how to add breakpoints within the browser or visual studio code for debugging.

bevy3d_ui

This example uses the bevy 3d game engine with leptos within webassembly.


Overview (`reactive_graph/README.md`)

An implementation of a fine-grained reactive system.

Fine-grained reactivity is an approach to modeling the flow of data through an interactive
application by composing together three categories of reactive primitives:

  1. Signals: atomic units of state, which can be directly mutated.
  2. Computations: derived values, which cannot be mutated directly but update whenever the signals
    they depend on change. These include both synchronous and asynchronous derived values.
  3. Effects: side effects that synchronize the reactive system with the non-reactive world
    outside it.

Signals and computations are "source" nodes in the reactive graph, because an observer can
subscribe to them to respond to changes in their values. Effects and computations are "subscriber"
nodes, because they can listen to changes in other values.

rust
use reactive_graph::{
    computed::ArcMemo,
    effect::Effect,
    prelude::{Read, Set},
    signal::ArcRwSignal,
};

let count = ArcRwSignal::new(1);
let double_count = ArcMemo::new({
    let count = count.clone();
    move |_| *count.read() * 2
});

// the effect will run once initially
Effect::new(move |_| {
    println!("double_count = {}", *double_count.read());
});

// updating `count` will propagate changes to the dependencies,
// causing the effect to run again
count.set(2);

This reactivity is called "fine grained" because updating the value of a signal only affects
the effects and computations that depend on its value, without requiring any diffing or update
calculations for other values.

This model is especially suitable for building user interfaces, i.e., long-lived systems in
which changes can begin from many different entry points. It is not particularly useful in
"run-once" programs like a CLI.

Design Principles and Assumptions

  • Effects are expensive. The library is built on the assumption that the side effects
    (making a network request, rendering something to the DOM, writing to disk) are orders of
    magnitude more expensive than propagating signal updates. As a result, the algorithm is
    designed to avoid re-running side effects unnecessarily, and is willing to sacrifice a small
    amount of raw update speed to that goal.
  • Automatic dependency tracking. Dependencies are not specified as a compile-time list, but
    tracked at runtime. This in turn enables dynamic dependency tracking: subscribers
    unsubscribe from their sources between runs, which means that a subscriber that contains a
    condition branch will not re-run when dependencies update that are only used in the inactive
    branch.
  • Asynchronous effect scheduling. Effects are spawned as asynchronous tasks. This means
    that while updating a signal will immediately update its value, effects that depend on it
    will not run until the next "tick" of the async runtime. (This in turn means that the
    reactive system is async runtime agnostic: it can be used in the browser with
    wasm-bindgen-futures, in a native binary with tokio, in a GTK application with glib,
    etc.)

The reactive-graph algorithm used in this crate is based on that of
Reactively, as described
in this article.


Overview (`reactive_stores/README.md`)

Stores

Stores are a data structure for nested reactivity.

The reactive_graph crate provides primitives for fine-grained reactivity
via signals, memos, and effects.

This crate extends that reactivity to support reactive access to nested structs, without the need to create nested signals.

Using the #[derive(Store)] macro on a struct creates a series of getters that allow accessing each field. Individual fields
can then be read as if they were signals. Changes to parents will notify their children, but changing one sibling field will
not notify any of the others, nor will it require diffing those sibling fields (unlike earlier solutions using memoized β€œslices”).

This is published for use with the Leptos framework but can be used in any scenario where reactive_graph is being used
for reactivity.


Overview (`reactive_stores_macro/README.md`)

This crate provides macro that are helpful or required when using the reactive_stores crate.


Overview (`docs/book/README.md`)

The Leptos book is now available at https://book.leptos.dev.

The source code for the book has moved to https://github.com/leptos-rs/book. Please open issues or make PRs in that repository.


Overview (`docs/book_ru/README.md`)

ΠŸΠ΅Ρ€Π΅Π²ΠΎΠ΄ Π² процСссС, ΠΊΠ½ΠΈΠ³Π° скоро Π±ΡƒΠ΄Π΅Ρ‚ доступна

Translation underway, book will be available soon


Overview (`examples/action-form-error-handling/README.md`)

Action Form Error Handling Example

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Execute cargo leptos watch to run this example.


Overview (`examples/axum_js_ssr/README.md`)

Leptos Axum JS SSR Example

This example shows the various ways that JavaScript may be included into
a Leptos application. The intent is to demonstrate how this may be done
and how it may cause the application to fail in an unexpected manner if
done incorrectly.

Quick Start

Run cargo leptos watch to run this example.


Overview (`examples/counter/README.md`)

Leptos Counter Example

This example creates a simple counter in a client side rendered app with Rust and WASM!

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/counter_isomorphic/README.md`)

Leptos Counter Isomorphic Example

This example demonstrates how to use a function isomorphically, to run a server side function from the browser and receive a result.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run cargo leptos watch to run this example.


Overview (`examples/counter_url_query/README.md`)

Leptos Query Counter Example

This example creates a simple counter whose state is persisted and synced in the url with query params.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/counter_without_macros/README.md`)

Leptos Counter Example

This example is the same like the counter but it's written without using macros and can be build with stable Rust.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/counters/README.md`)

Leptos Counters Example

This example showcases a basic leptos app with many counters. It is a good example of how to setup a basic reactive app with signals and effects, and how to interact with browser events.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/directives/README.md`)

Leptos Directives Example

This example showcases a basic leptos app that shows how to write and use directives.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/error_boundary/README.md`)

Leptos `` Example

This example shows how to handle basic errors using Leptos.

Getting Started

See the Examples README for setup and run instructions.

Testing

This project is configured to run start and stop of processes for integration tests without the use of Cargo Leptos or Node.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/errors_axum/README.md`)

Leptos Errors Demonstration with Axum

This example demonstrates how Leptos Errors can work with an Axum backend on a server.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run cargo leptos watch to run this example.


Overview (`examples/fetch/README.md`)

Client Side Fetch

This example shows how to fetch data from the client in WebAssembly.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/hackernews/README.md`)

Leptos Hacker News Example

This example creates a basic clone of the Hacker News site. It showcases Leptos' ability to create both a client-side rendered app, and a server side rendered app with hydration, in a single repository

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open or cargo leptos watch to run this example.


Overview (`examples/hackernews_axum/README.md`)

Leptos Hacker News Example with Axum

This example creates a basic clone of the Hacker News site. It showcases Leptos' ability to create both a client-side rendered app, and a server side rendered app with hydration, in a single repository. This repo differs from the main Hacker News example by using Axum as it's server.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open or cargo leptos watch to run this example.


Overview (`examples/hackernews_islands_axum/README.md`)

Leptos Hacker News Example with Axum

This example creates a basic clone of the Hacker News site. It showcases Leptos' ability to:

  • Create a client-side rendered app
  • Create a server side rendered app with hydration
  • Precompress static assets and bundle those in with the server binary

This repo differs from the main Hacker News example by using Axum as it's server, precompressing and embedding static assets into the binary, and dynamically compressing the generated HTML.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run cargo leptos watch --release -P to run this example.


Overview (`examples/hackernews_js_fetch/README.md`)

Leptos Hacker News Example with Axum

This example uses the basic Hacker News example as its basis, but shows how to run the server side as WASM running in a JS environment. In this example, Deno is used as the runtime.

Server Side Rendering with Deno

To run the Deno version, run

bash
deno task build
deno task start

Overview (`examples/islands/README.md`)

Leptos Todo App Sqlite with Axum

This example creates a basic todo app with an Axum backend that uses Leptos' server functions to call sqlx from the client and seamlessly run it on the server.

Getting Started

See the Examples README for setup and run instructions.

E2E Testing

See the E2E README for more information about the testing strategy.

Rendering

See the SSR Notes for more information about Server Side Rendering.

Quick Start

Run cargo leptos watch to run this example.


Overview (`examples/islands_router/README.md`)

Work in Progress

This example is something I wrote on a long layover in the Orlando airport in July. (It was really hot!)

It is the culmination of a couple years of thinking and working toward being able to do this, which you can see
described pretty well in the pinned roadmap issue (#1830) and its discussion of different modes of client-side
routing when you use islands.

This uses only server rendering, with no actual islands, but still maintains client-side state across page navigations.
It does this by building on the fact that we now have a statically-typed view tree to do pretty smart updates with
new HTML from the client, with extremely minimal diffing.


Overview (`examples/js-framework-benchmark/README.md`)

Leptos benchmark example

This example is adoptation of code from js-framework-benchmark.
This example creates a large table with randomized entries, it also shows usage of template macro and For component.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/lazy_routes/README.md`)

Regression Tests

This example functions as a catch-all for all current and future regression
test cases that typically happens at integration.

Quick Start

Run cargo leptos watch --split to run this example.


Overview (`examples/parent_child/README.md`)

Parent Child Example

This example highlights four different ways that child components can communicate with their parent:

  1. ``: passing a WriteSignal as one of the child component props,
    for the child component to write into and the parent to read
  2. ``: passing a closure as one of the child component props, for
    the child component to call
  3. ``: adding a simple event listener on the child component itself
  4. ``: providing a context that is used in the component (rather than prop drilling)

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/portal/README.md`)

Leptos Portal Example

This example showcases a basic leptos app with a portal.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/regression/README.md`)

Regression Tests

This example functions as a catch-all for all current and future regression
test cases that typically happens at integration.

Quick Start

Run cargo leptos watch to run this example.


Overview (`examples/router/README.md`)

Leptos Router Example

This example demonstrates how Leptos’s router works for client side routing.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/server_fns_axum/README.md`)

Leptos Todo App Sqlite with Axum

This example creates a basic todo app with an Axum backend that uses Leptos' server functions to call sqlx from the client and seamlessly run it on the server.

Getting Started

See the Examples README for setup and run instructions.

E2E Testing

See the E2E README for more information about the testing strategy.

Rendering

See the SSR Notes for more information about Server Side Rendering.

Quick Start

Run cargo leptos watch to run this example.


Overview (`examples/slots/README.md`)

Leptos `` Example

This example shows how to use Slots in Leptos.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/spread/README.md`)

Leptos Attribute and EventHandler spreading Example

This example creates a simple element in a client side rendered app with Rust and WASM!

Dynamic sets of attributes and event handler are spread onto the element with little effort.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/ssr_modes/README.md`)

SSR Modes Example

This example shows the different "rendering modes" that can be used while server-side rendering an application.

Getting Started

See the Examples README for setup and run instructions.

Server-Side Rendering Modes

  1. Synchronous: Serve an HTML shell that includes fallback for any Suspense. Load data on the client, replacing fallback once they're loaded.

    • Pros: App shell appears very quickly: great TTFB (time to first byte).
    • Cons: Resources load relatively slowly; you need to wait for JS + Wasm to load before even making a request.
  2. Out-of-order streaming: Serve an HTML shell that includes fallback for any Suspense. Load data on the server, streaming it down to the client as it resolves, and streaming down HTML for Suspense nodes.

    • Pros: Combines the best of synchronous and async, with a very fast shell and resources that begin loading on the server.
    • Cons: Requires JS for suspended fragments to appear in correct order. Weaker meta tag support when it depends on data that's under suspense (has already streamed down <head>)
  3. In-order streaming: Walk through the tree, returning HTML synchronously as in synchronous rendering and out-of-order streaming until you hit a Suspense. At that point, wait for all its data to load, then render it, then the rest of the tree.

    • Pros: Does not require JS for HTML to appear in correct order.
    • Cons: Loads the shell more slowly than out-of-order streaming or synchronous rendering because it needs to pause at every Suspense. Cannot begin hydration until the entire page has loaded, so earlier pieces
      of the page will not be interactive until the suspended chunks have loaded.
  4. async: Load all resources on the server. Wait until all data are loaded, and render HTML in one sweep.

    • Pros: Better handling for meta tags (because you know async data even before you render the <head>). Faster complete load than synchronous because async resources begin loading on server.
    • Cons: Slower load time/TTFB: you need to wait for all async resources to load before displaying anything on the client.

Quick Start

Run cargo leptos watch to run this example.


Overview (`examples/ssr_modes_axum/README.md`)

SSR Mode Axum Example

This example shows the different "rendering modes" that can be used while server-side rendering an application.

Getting Started

See the Examples README for setup and run instructions.

Server-Side Rendering Modes

  1. Synchronous: Serve an HTML shell that includes fallback for any Suspense. Load data on the client, replacing fallback once they're loaded.

    • Pros: App shell appears very quickly: great TTFB (time to first byte).
    • Cons: Resources load relatively slowly; you need to wait for JS + Wasm to load before even making a request.
  2. Out-of-order streaming: Serve an HTML shell that includes fallback for any Suspense. Load data on the server, streaming it down to the client as it resolves, and streaming down HTML for Suspense nodes.

    • Pros: Combines the best of synchronous and async, with a very fast shell and resources that begin loading on the server.
    • Cons: Requires JS for suspended fragments to appear in correct order. Weaker meta tag support when it depends on data that's under suspense (has already streamed down <head>)
  3. In-order streaming: Walk through the tree, returning HTML synchronously as in synchronous rendering and out-of-order streaming until you hit a Suspense. At that point, wait for all its data to load, then render it, then the rest of the tree.

    • Pros: Does not require JS for HTML to appear in correct order.
    • Cons: Loads the shell more slowly than out-of-order streaming or synchronous rendering because it needs to pause at every Suspense. Cannot begin hydration until the entire page has loaded, so earlier pieces
      of the page will not be interactive until the suspended chunks have loaded.
  4. async: Load all resources on the server. Wait until all data are loaded, and render HTML in one sweep.

    • Pros: Better handling for meta tags (because you know async data even before you render the <head>). Faster complete load than synchronous because async resources begin loading on server.
    • Cons: Slower load time/TTFB: you need to wait for all async resources to load before displaying anything on the client.

Quick Start

Run cargo leptos watch to run this example.


Overview (`examples/static_routing/README.md`)

Static Routing Example

This example shows the static routing features, which can be used to generate the HTML content for some routes before a request.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run cargo leptos watch to run this example.


Overview (`examples/stores/README.md`)

Stores Example

This example shows how to use reactive stores, by building a client-side rendered TODO application.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/subsecond_hot_patch/README.md`)

Hot Patching with `dx`

This is an experimental example exploring how to combine Leptos with the binary hot-patching provided by Dioxus's subsecond library and dx cli.

Serving Your App

This requires installing the Dioxus CLI version 0.7.0. At the time I'm writing this README, that does not yet have a stable release. Once dioxus-cli 0.7.0 has been released, you should use the latest stable release. Until then, I'd suggest installing from git:

sh
cargo install dioxus-cli --git https://github.com/DioxusLabs/dioxus

Then you can run the example with dx serve --hot-patch --platform web.

Hot Patching

Changes to the your application should be reflected in your app without a full rebuild and reload.

Limitatations

Currently we only support hot-patching for reactive view functions. You probably want to use AnyView (via .into_any()) on any views that will be hot-patched, so they can be rebuilt correctly despite their types changing when the structure of the view tree changes.

If you are using leptos_router this actually works quite well, as every route’s view is erased to AnyView and the router itself is a reactive view function: in other words, changes inside any route should be hot-patched in any case.

Note that any hot-patch will cause all render effects to run again. This means that some client-side state (like the values of signals) will be wiped out.

Build Tooling

The preference of the Dioxus team is that all hot-patching work that uses their subsecond also use dioxus-cli. As this demo shows, it's completely possible to use dioxus-cli to build and run a Leptos project. We do not plan to build subsecond into our own build tooling at this time.

This is an experiment/POC. It is being published because members of the community have found it useful and have asked for the support to be merged in its current state. Further development and bugfixes are a relatively low priority at this time.


Overview (`examples/suspense_tests/README.md`)

Suspense Test Example

This example demonstrates the <Suspense/> behavior.

Getting Started

See the Examples README for setup and run instructions.

Test Strategy

See the E2E README to learn about the web testing strategy for this project.

Quick Start

Run cargo leptos watch to run this example.


Overview (`examples/tailwind_actix/README.md`)

Leptos Starter Template

This is a template demonstrating how to integrate TailwindCSS with the Leptos web framework and the cargo-leptos tool.

Getting Started

See the Examples README for setup and run instructions.

Tailwind

You can install Tailwind using npm:

bash
npm install -D tailwindcss

If you'd rather not use npm, you can install the Tailwind binary here.

Setting up with VS Code and Additional Tools

If you're using VS Code, add the following to your settings.json

json
"emmet.includeLanguages": {
    "rust": "html",
    "*.rs": "html"
  },
  "tailwindCSS.includeLanguages": {
      "rust": "html",
      "*.rs": "html"
  },
  "files.associations": {
      "*.rs": "rust"
  },
  "editor.quickSuggestions": {
    "other": "on",
    "comments": "on",
    "strings": true
  },
  "css.validate": false,

Install Tailwind CSS Intellisense.

Install VS Browser extension (allows you to open a browser at the right window).

Allow vscode Ports forward: 3000, 3001.

Attribution

Many thanks to GreatGreg for putting together this guide. You can find the original, with added details, here.


Overview (`examples/tailwind_axum/README.md`)

Leptos with Axum + TailwindCSS Template

This is a template demonstrating how to integrate TailwindCSS with the Leptos web framework, Axum server, and the cargo-leptos tool.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run cargo leptos watch to run this example.

Tailwind Migration

If you're updating from Tailwind 3 to Tailwind 4, it would be informative to view the tailwind migration document as things have changed.


Overview (`examples/tailwind_csr/README.md`)

Leptos Starter Template

This is a template demonstrating how to integrate TailwindCSS with the Leptos web framework and the trunk tool.

Getting Started

See the Examples README for setup and run instructions.

Tailwind

Trunk.toml is configured to build the CSS automatically.

You can install Tailwind using npm:

bash
npm install -D tailwindcss

If you'd rather not use npm, you can install the Tailwind binary here.

Setting up with VS Code and Additional Tools

If you're using VS Code, add the following to your settings.json

json
"emmet.includeLanguages": {
    "rust": "html",
    "*.rs": "html"
  },
  "tailwindCSS.includeLanguages": {
      "rust": "html",
      "*.rs": "html"
  },
  "files.associations": {
      "*.rs": "rust"
  },
  "editor.quickSuggestions": {
    "other": "on",
    "comments": "on",
    "strings": true
  },
  "css.validate": false,

Install Tailwind CSS Intellisense.

Install VS Browser extension (allows you to open a browser at the right window).

Allow vscode Ports forward: 3000, 3001.

Attribution

Many thanks to GreatGreg for putting together this guide. You can find the original, with added details, here.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/timer/README.md`)

Leptos Timer Example

This example creates a simple timer based on setInterval in a client side rendered app with Rust and WASM.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/todo_app_sqlite/README.md`)

Leptos Todo App Sqlite

This example creates a basic todo app with an Actix backend that uses Leptos' server functions to call sqlx from the client and seamlessly run it on the server.

Getting Started

See the Examples README for setup and run instructions.

E2E Testing

See the E2E README for more information about the testing strategy.

Rendering

See the SSR Notes for more information about Server Side Rendering.

Quick Start

Run cargo leptos watch to run this example.


Overview (`examples/todo_app_sqlite_axum/README.md`)

Leptos Todo App Sqlite with Axum

This example creates a basic todo app with an Axum backend that uses Leptos' server functions to call sqlx from the client and seamlessly run it on the server.

Getting Started

See the Examples README for setup and run instructions.

E2E Testing

See the E2E README for more information about the testing strategy.

Rendering

See the SSR Notes for more information about Server Side Rendering.

Quick Start

Run cargo leptos watch to run this example.


Overview (`examples/todo_app_sqlite_csr/README.md`)

Leptos Todo App Sqlite with CSR

This example shows how to combine client-side rendering with server functions, i.e., using server functions as a convenient way to create an ad hoc API, but without using server-side rendering and hydration.

Getting Started

See the Examples README for setup and run instructions.

E2E Testing

See the E2E README for more information about the testing strategy.

Rendering

See the SSR Notes for more information about Server Side Rendering.

Quick Start

Run cargo leptos watch to run this example.


Overview (`examples/todomvc/README.md`)

Leptos TodoMVC

This is a Leptos implementation of the TodoMVC example common to many frameworks. This is a relatively-simple application but shows off features like interaction between components and state management.

Getting Started

See the Examples README for setup and run instructions.

Quick Start

Run trunk serve --open to run this example.


Overview (`examples/websocket/README.md`)

Leptos WebSocket

This example creates a basic WebSocket echo app.

Getting Started

See the Examples README for setup and run instructions.

E2E Testing

See the E2E README for more information about the testing strategy.

Rendering

See the SSR Notes for more information about Server Side Rendering.

Quick Start

Run cargo leptos watch to run this example.


Overview (`projects/bevy3d_ui/README.md`)

Bevy 3D UI Example

This example combines a leptos UI with a bevy 3D view.
Bevy is a 3D game engine written in rust that can be compiled to web assembly by using the wgpu library.
The wgpu library in turn can target the newer webgpu standard or the older webgl for web browsers.

In the case of a desktop application, if you wanted to use a styled ui via leptos and a 3d view via bevy
you could also combine this with tauri.

Quick Start

It's best to use a web browser with webgpu capability for best results such as Chrome or Opera.


Overview (`projects/counter_dwarf_debug/README.md`)

Debugging Leptos Counter Example in Browser and VSCode

This example builds on the simple counter by adding breakpoints and single stepping the source code for debugging.
Both within the browser and VSCode.
This uses a new feature of wasm called Dwarf which is a form of source code mapping.

Note variable inspection during the breakpoints doesn't seem to work at this stage.

Quick Start

  • Install the requirements below
  • Open this directory within visual studio code
  • Add a breakpoint to the code
  • Launch the example using the visual studio code debug launcher

How This Works

Html Changes

First we need to make a change to the index.html file

From this

html
<link data-trunk rel="rust" data-wasm-opt="z"/>

To this

html
<link data-trunk rel="rust" data-keep-debug="true" data-wasm-opt="z"/>

This instructs the rust trunk utility to pass a long an option to wasm-bindgen called --keep-debug
This option bundles in a type of sourcemap into the built wasm file.
Be aware that this will make the wasm file much larger.

Browser Changes

Next we need to allow the browser to read the DWARF data from the wasm file.
For Chrome / Opera there's an extension here that needs to be installed.

Debugging within the Browser

Within the browser's dev console it should now be possible to view the rust source code and add breakpoints.

Debugging within VSCode

Note this is still experimental, although I have managed to get breakpoints working under VSCode.
So far I've only tried this within a windows environment.

In order to have the breakpoints land at the correct position.
We need to install the following VSCode extension.

Within the browser launch section under launch.json we need to set userDataDir to false in order for the DWARF browser extension to be loaded.

json
{
    "name": "Launch Browser Chrome",
    "request": "launch",
    "type": "chrome",
    "url": "http://localhost:8080",
    "webRoot": "${workspaceFolder}/dist",
    // Needed to keep the dwarf extension in the browser
    "userDataDir": false,
  },

Now we should be able to add breakpoints within visual studio code while debugging the rust wasm.


Overview (`projects/hexagonal-architecture/README.md`)

Leptos Hexagonal Design

This Blog Post / Github Repository is about applying principles of hexagonal design
- Isolating Business Logic from Sub Domains
- Decoupling design to improve flexibility and testablity
- Applying the principles hierachically so that sub domains which talk to external services also implement also implement hexagonal architecture

There are specific constraints that guide our design decisions

  • Server Functions Can't be Generic
  • Boxed Traits Objects Have overhead, so we only want to use as much generic code as possible avoid Trait Objects

The way this works is we define the functionality of our program in the main domain (i.e the business problem and processes our app is trying to solve / proceduralize). We then create sub domains and external services, although they are represented the same. External services are usually the end nodes of your app's architectural graph. Our main application builds it's service layout using configuration flags.

rust
pub fn config() -> MainAppHandlerAlias {
    cfg_if::cfg_if! {
                if #[cfg(feature="open_ai_wrapper")] {
                    fn server_handler_config_1() -> MainAppHandler<
                        AuthService<PostgresDb, Redis>,
                        AiMessageGen<PostgresDb,OpenAiWrapper>,
                        > {
                        MainAppHandler::new_with_postgres_and_redis_open_ai()
                    }
                    server_handler_config_1()
                } else {
                    fn server_handler_config_2() -> MainAppHandler<
                        AuthService<MySql, MemCache>,
                        OtherAiMessageGen<MySql,HuggingFaceWrapper>,
                        > {
                        MainAppHandler::new_with_my_sql_memcache_hugging_face()
                    }           
                    server_handler_config_2()
                }
            }
}

And we pass in our handler which implements a trait

rust
pub trait HandlerServerFn {
    pub fn server_fn_1_inner(&self);
}
impl<S,S2> HandlerServerFn for MainAppHandler<S:SubDomain1Trait,S2:SubDomain2Trait> {
    pub fn server_fn_1_inner(&self) {
        // do thing
    }
}

in our main fn we produce our applications service graph and pass it to our leptos router.

rust
main () {
   let leptos_options = conf.leptos_options;
    let routes = generate_route_list(crate::app::App);
    // our feature flag based config function.
    let handler = config();
    let handler_c = handler.clone();
    // we implement FromRef<ServerState> for LeptosOptions
    let server_state = ServerState {
        handler,
        leptos_options: leptos_options.clone(),
    };
    let app = Router::new()
        .leptos_routes_with_context(
            &server_state,
            routes,
            // We pass in the MainAppHandler struct as context so we can fetch it anywhere context is available on the server.
            // This includes in middleware we define on server functions (see middleware.rs)
            move || provide_context(handler_c.clone()),
            {
                let leptos_options = leptos_options.clone();
                move || shell(leptos_options.clone())
            },
        )
        .fallback(leptos_axum::file_and_error_handler::<
            ServerState<HandlerStructAlias>,
            _,
        >(shell))
        .with_state(server_state);
}

and then in our server functions

rust
#[server]
pub async fn server_fn_1() -> Result<(),ServerFnError> {
    // we type alias every variation of our services we plan on configuring. The alternative is using Box<dyn Trait> which isn't bad - just slower.
    Ok(expect_context::<MainAppHandlerAlias>().server_fn_1_inner())
}

And then we can mock and service trait in any combination like so

rust
#[tokio::test]
    pub async fn test_subdomain_1_with_mocks() -> Result<(), Box<dyn Error>> {
        let mut mock_external_service_1 = MockExternalServiceTrait1::new();
        mock_external_service_1
            .expect_external_service_1_method()
            .returning(|| {
                println!("Mock external service 1");
                Ok(ExternalService1Data)
            });
        let mut mock_external_service_2 = MockExternalServiceTrait2::new();
        mock_external_service_2
            .expect_external_service_2_method()
            .returning(|| {
                println!("Mock external service 2");
                Ok(ExternalService2Data)
            });
        let real_subdomain_1_with_mock_externals = SubDomainStruct1 {
            external_service_1: mock_external_service_1,
            external_service_2: mock_external_service_2,
        };
        let data = real_subdomain_1_with_mock_externals
            .sub_domain_1_method()
            .await?;
        assert_eq!(data, SubDomain1Data);
        Ok(())
    }

Check out the code in the repository for a working example.

Run the tests with

cargo test --features ssr
and otherwise run
cargo leptos serve
and navigate to 127.0.0.1:3000

here's a picture


Overview (`projects/login_with_token_csr_only/README.md`)

Leptos Login Example

This example demonstrates a scenario of a client-side rendered application
that uses an existing API that you cannot or do not want to change.
The authentications of this example are done using an API token.

The api-boundary crate contains data structures that are used by the server and the client.

Getting Started

See the Examples README for setup and run instructions.

You will also need to run cargo make stop to end the server process.


Overview (`projects/meilisearch-searchbar/README.md`)

This show how to integrate meilisearch with a leptos app, including a search bar and showing the results to the user.

We'll run meilisearch locally, as opposed to using their cloud service.

To get started install meilisearch into this example's root.

sh
curl -L https://install.meilisearch.com | sh

Run it.

sh
./meilisearch

Then set the environment variable and serve the app. I've included the address of my own local meilisearch server.
I didn't provide a password to meilisearch during my setup, and I didn't provide one in my environment variables either.

sh
MEILISEARCH_URL=http://localhost:7700 && cargo leptos serve

Navigate to 127.0.0.1:3000 and start typing in popular American company names. (Boeing, Pepsi, etc)

Thoughts, Feedback, Criticism, Comments?

Send me any of the above, I'm @sjud on leptos discord. I'm always looking to improve and make these projects more helpful for the community. So please let me know how I can do that. Thanks!


Overview (`projects/nginx-mpmc/README.md`)

Nginx Multiple Server Multiple Client Example

This example shows how multiple clients can communicate with multiple servers while being shared over a single domain i.e localhost:80 using nginx as a reverse proxy.

How to run this example

sh
./run.sh

Or

sh
./run_linux.sh

This will boot up nginx via it's docker image mapped to port 80, and the four servers. App-1, App-2, Shared-Server-1, Shared-Server-2.

App-1, And App-2 are SSR rendering leptos servers.

If you go to localhost (you'll get App-1), and localhost/app2 (you'll get app2).

The two shared servers can be communicated with via actions and local resources, or resources (if using CSR).

create_resource Won't work as expected, when trying to communicate to different servers. It will instead try to run the server function on the server you are serving your server side rendered content from. This will cause errors if your server function relies on state that is not present.

When you are done with this example, run

sh
./kill.sh

Casting ctrl-c multiple times won't close all the open programs.

Thoughts, Feedback, Criticism, Comments?

Send me any of the above, I'm @sjud on leptos discord. I'm always looking to improve and make these projects more helpful for the community. So please let me know how I can do that. Thanks!


Overview (`projects/openapi-openai-api-swagger-ui/README.md`)

#OpenAPI Swagger-Ui OpenAI GPT

This example shows how to document server functions via OpenAPI schema generated using Utoipa and serve the swagger ui via /swagger-ui endpoint. More than that, this example shows how to take said OpenAPI spec and turn it into a function list to feed to OpenAI's chat completion endpoint to generate the JSON values to feed back into our server functions.

The example shows an input and if you tell it to do something that is covered, say hello, or generate a list of names it will do that.

To use the AI part of this project provide your openAPI key in an environment variable when running cargo leptos.

sh
OPENAI_API_KEY=my_secret_key cargo leptos serve

Thoughts, Feedback, Criticism, Comments?

Send me any of the above, I'm @sjud on leptos discord. I'm always looking to improve and make these projects more helpful for the community. So please let me know how I can do that. Thanks!


Overview (`projects/ory-kratos/README.md`)

Leptos Ory Kratos Integration (With Axum)

This repo used start-axum-workspace as a base.

How to run the example.

Run in different terminal windows (for the best result)

sh
cargo leptos serve
sh
docker compose up
sh
cargo test --test app_suite

This will run our server, set up our compose file (MailCrab, Ory Kratos, Ory Ketos) and run the test suite that walks through logging in, registration, verification etc.

The e2e testing uses chromiumoxide and does things like monitor network requests, console messages, take screenshots during the flow and produces them when any of our feature tests fail. This can be a helpful starting point in debugging. Currently it just prints the output into files in the e2e directory but it could be modified to pipe them somewhere like a tool to help with the development process.

High Level Overview

Our project runs a leptos server alongside various Ory Kratos. Kratos provides identification, and we use it when registering users, and credentialing them.

A normal flow would look something like:

  • I go to the homepage,I click register
  • I am redirected to the register page, the register page isn't hardcoded but is rendered by parsing the UI data structure given by Ory Kratos. The visible portions correspond to the fields we've set in our ./kratos/email.schema.json schema file, but it includes hidden fields (i.e a CSRF token to prevent CSRF). This project includes unstyled parsing code for the UI data structure.
  • I sign up with an email and password
  • Our leptos server will intercept the form data and then pass it on to the ory kratos service.
  • Ory Kratos validates those inputs given the validation criteria ./kratos/email.schema.json schema file
  • Ory Kratos then verifies me by sending me an email.
  • In this example we catch the email with an instance of mailcrab (an email server for testing purposes we run in our docker compose) . You can use mailcrab locally 127.0.0.1:1080
  • I look inside the email, I see a code and a link where I will input the code.
  • I click through and input the code, and I am verified.
  • When I go to the login page, it's rendered based on the same method as the registration page. I.e Kratos sends a UI data structure which is parsed into the UI we show the user.
  • I use my password and email on the login page to login.
  • Again, Our leptos server acts as the inbetween between the client and the Ory Kratos service. There were some pecularities between the CSRF token being set in the headers (which Ory Kratos updates with every step in the flow), SSR, and having the client communicate directly with Ory Kratos which lead me to use this approach where our server is the intermediary between the client and Ory Kratos.
  • Ory Kratos is session based, so after it recieves valid login credentials it creates a session and returns the session token. The session token is passed via cookies with every future request. All this does is establish the identity of the caller, to perform authentication we need a way to establish permissions given an individuals identity and how that relates to the content on the website. In this example I just use tables in the database but this example could be extended to use Ory Ketos, with is to Authorization a Ory Kratos is to Identification.
  • When given bad input in a field, Ory Kratos issues a new render UI data structure with error messages and we rerender the login page.

    With regards to Ory Oathkeeper And Ory Ketos.

    Ory Oathkeeper is a reverse proxy that sits between your server and the client, it takes the session token, looks to see what is being requested in the request and then checks the configuration files of your Ory Services to see if such a thing is allowed. It will communicate with the Ory services on your behalf and then pass on the authorized request to the appropriate location or reject it otherwise.

    Ory Ketos is the authorization part of the Ory suite, Ory Kratos simplies identifies the user (this is often conflated with authorization but authorization is different). Authorization is the process of after having confirmed a user's identity provisioning services based on some permission structure. I.e Role Based Authorization, Document based permissions, etc. Ory Ketos uses a similar configuration file based set up to Ory Kratos.

    Instead of either of those, in this example we use an extractor to extract the session cookie and verify it with our kratos service and then perform our own checks. This is simpler to set up, more inutitive, and thus better for smaller projects. Identification is complicated, and it's nice to have it be modularized for whatever app we are building. This will save a lot of time when building multiple apps. The actual provisioning of services for most apps is much simpler, i.e database lookup tied to identification and some logic checks. Is the user preiumum? How much have they used the API compared to the maximum? Using Ory Kratos can reduce complexity and decrease your time to market, especially over multiple attempts.

    In production you'd have a virtual private server and you'd serve your leptos server behind Nginx, Nginx routes the calls to the Leptos Server and never to our Ory Kratos. Our Rust server handles all the communication between the client and Ory services. This is simpler from an implementation perspective then including Ory Oathkeeper and Ory Ketos. Ory Kratos/Ketos presume all api calls they recieve are valid by default, so it's best not to expose them at all to any traffic from the outside world. And when building our leptos app we'll have a clear idea about when and how these services are being communicated with when our service acts as the intermediary.

    How this project is tested

    We use Gherkin feature files to describe the behavior of the application. We use cucumber as our test harness and match the feature files to chromiumoxide code to drive a local chromium application. I'm using e2e testing mostly to confirm that the service provides the value to the user, in this case just authorization testing. And that, that value proposition doesn't break when we change some middleware code that touches everything etc.

    The ids crate includes a list of static strings that we'll use in our chromiumoxide lookups and our frontend to make our testing as smooth as possible. There are other ways to do this, such as find by text, which would find the "Sign Up" text and click it etc. So these tests don't assert anything with regards to presentation, just functionality.

    How to use mkcert to get a locally signed certificate (and why)

    We need to use https because we are sending cookies with the Secure; flag, cookies with the Secure flag can't be used
    unless delivered over https. Since we're using chromedriver for e2e testing let's use mkcert to create a cert that will allow
    https://127.0.0.1:3000/ to be a valid url.
    Install mkcert and then

    sh
    mkcert -install localhost 127.0.0.1 ::1

    Copy your cert.pem, key.pem and rootCA.pem into this crate's root.

    Thoughts, Feedback, Criticism, Comments?

    Send me any of the above, I'm @sjud on leptos discord. I'm always looking to improve and make these projects more helpful for the community. So please let me know how I can do that. Thanks!


    Overview (`projects/session_auth_axum/README.md`)

    Leptos Authenticated Todo App Sqlite with Axum

    This example creates a basic todo app with an Axum backend that uses Leptos' server functions to call sqlx from the client and seamlessly run it on the server. It lets you login, signup, and submit todos as different users, or a guest.

    Getting Started

    See the Examples README for setup and run instructions.

    Quick Start

    Run cargo leptos watch to run this example.


    Overview (`projects/sitemap_axum/README.md`)

    Sitemaps with Axum

    This project demonstrates how to serve a sitemap file using Axum using dynamic data (like blog posts in this case). An example Postgres database is used data source for storing blog post data that can be used to generate a dynamic site map based on blog post slugs. There's lots of sitemap crates, though this example uses the xml for example purposes.

    Quick Start

    We use Docker to provide a Postgres database for this sample, so make sure you have it installed.

    sh
    $ docker -v
    Docker version 25.0.3, build 4debf41

    Once Docker has started on you local machine, run (make sure to have cargo-make installed):

    sh
    $ cargo make run

    This will handle spinning up a Postgres container, initializing the example database, and launching the local dev server.


    Overview (`projects/sso_auth_axum/README.md`)

    Leptos SSO Authenticated Email Display App with Axum

    Overview

    This project demonstrates various methods of implementing Single Sign-On (SSO) authorization using OAuth, specifically with the OAuth2 library. The primary focus is on the Authorization Code Grant flow.

    Process Flow

    1. Initiating Sign-In: When a user clicks the 'Sign In With {THIRD PARTY SERVICE}' button, the request is sent to a server function. This function retrieves an authorization URL from the third-party service.

    2. CSRF Token Handling: During the URL fetch, a CSRF_TOKEN is generated and confirmed by the service to mitigate Cross-Site Request Forgery attacks. Learn more about CSRF here. This token is stored on our server.

    3. User Redirection: Post-login, users are redirected to our server with a URL formatted as follows:
      http://your-redirect-uri.com/callback?code=AUTHORIZATION_CODE&state=CSRF_TOKEN
      Note: Additional parameters like Scope and Client_ID may be included by the service.

    4. Token Acquisition: The 'code' parameter in the URL is not the actual service token. Instead, it's used to fetch the token. We verify the CSRF_TOKEN in the URL against our server's stored token for security.

    5. Access Token Usage: With a valid CSRF_TOKEN, we use the AUTHORIZATION_CODE in an HTTP Request to the third-party service. The response typically includes:

    • An access token
    • An expires_in value (time in seconds until token expiration)
    • A refresh token (used to renew the access token)
    1. Email Retrieval and Display: The access token allows us to retrieve the user's email. This email is then displayed in our Email Display App.

    2. Session Management: The expires_in value is sent to the client. The client uses this to set a timeout, ensuring that if the session is still active (the window hasn't been closed), it automatically triggers a token refresh when required.

    Client Side Rendering

    This example cannot be built as a trunk standalone CSR-only app. Only the server may directly connect to the database.

    Server Side Rendering with cargo-leptos

    cargo-leptos is now the easiest and most featureful way to build server side rendered apps with hydration. It provides automatic recompilation of client and server code, wasm optimisation, CSS minification, and more! Check out more about it here

    Env Vars

    Commands that run the program, cargo leptos watch, cargo leptos serve, cargo run etc... All need the following Environment variables
    G_AUTH_CLIENT_ID : This is the client ID given to you by google.
    G_AUTH_SECRET : This is the secret given to you by google.
    NGROK : this is the ngrok endpoint you get when you run ngrok http 3000

    Ngrok Google Set Up

    After running your app, run

    bash
    ngrok http 3000

    Then use google api's and services, go to credentials, create credentials, add your app name, and use the ngrok url as the origin
    and use the ngrok url with /g_auth as the redirect url. That will look like this https://362b-24-34-20-189.ngrok-free.app/g_auth
    Save you client ID and secret given to you by google. Use them as Envars when you run the program as below

    bash
    REDIRECT_URL={ngrok_redirect_url} G_AUTH_CLIENT_ID={google_credential_client_id} G_AUTH_SECRET={google_credential_secret} {your command here...}
    1. Install cargo-leptos
    bash
    cargo install --locked cargo-leptos
    1. Build the site in watch mode, recompiling on file changes
    bash
    cargo leptos watch

    Open browser on http://localhost:3000/

    1. When ready to deploy, run
    bash
    cargo leptos build --release

    Server Side Rendering without cargo-leptos

    To run it as a server side app with hydration, you'll need to have wasm-pack installed.

    1. Edit the [package.metadata.leptos] section and set site-root to ".". You'll also want to change the path of the <StyleSheet / > component in the root component to point towards the CSS file in the root. This tells leptos that the WASM/JS files generated by wasm-pack are available at ./pkg and that the CSS files are no longer processed by cargo-leptos. Building to alternative folders is not supported at this time. You'll also want to edit the call to get_configuration() to pass in Some(Cargo.toml), so that Leptos will read the settings instead of cargo-leptos. If you do so, your file/folder names cannot include dashes.
    2. Install wasm-pack
    bash
    cargo install wasm-pack
    1. Build the Webassembly used to hydrate the HTML from the server
    bash
    wasm-pack build --target=web --debug --no-default-features --features=hydrate
    1. Run the server to serve the Webassembly, JS, and HTML
    bash
    cargo run --no-default-features --features=ssr

    Overview (`projects/tauri-from-scratch/README.md`)

    Tauri from scratch

    This is a guide on how to build a leptos tauri project from scratch without using a template.

    First

    sh
    cargo new leptos_tauri_from_scratch

    Then, make our two separate project folders. We need one for our actual app, src-orig/ and the other is required when using cargo tauri

    sh
    mkdir src-orig && mkdir src-tauri

    Delete the original src folder.

    sh
    rm -r src

    Rewrite the Cargo.toml file in our crate root to the following.

    toml
    [workspace]
    resolver = "2"
    members = ["src-tauri", "src-orig"]
    
    [profile.release]
    codegen-units = 1
    lto = true

    We'll list our workspace members. codegen-units = 1 and lto = true are good things to have for our eventual release, they make the wasm file smaller.

    What we're going to do is use cargo leptos for building our SSR server and we'll call trunk from cargo tauri for building our CSR client that we bundle into our different apps.

    Let's add a Trunk.toml file.

    toml
    [build]
    target = "./src-orig/index.html"
    
    [watch]
    ignore = ["./src-tauri"]

    The target of index.html is what trunk uses to build the wasm and js files that we'll need for the bundling process when we call cargo tauri build. We'll get the resulting files in a src-orig/dist folder.

    Create the index.html file

    sh
    touch src-orig/index.html

    Let's fill it with

    html
    <!DOCTYPE html>
    <html>
      <head>
        <link
          data-trunk
          rel="rust"
          data-wasm-opt="z"
          data-bin="leptos_tauri_from_scratch_bin"
        />
        <link rel="icon" type="image/x-icon" href="favicon.ico" />
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      </head>
      <body></body>
    </html>

    This line

    html
    <link
      data-trunk
      rel="rust"
      data-wasm-opt="z"
      data-bin="leptos_tauri_from_scratch_bin"
    />

    Tells trunk we want to compile our wasm to be small with opt="z" and that our binary will be named "leptos_tauri_from_scratch_bin".

    We need to specify that our binary will be a different name than our project name because we are also going to get a wasm file from our library and if we don't use different names then cargo tauri will get confused.

    More specifically two wasm artifacts will be generated, one for the lib and the other for the binary and it won't know which to use.

    Create a favicon that we referenced.

    sh
    mkdir public
    curl https://raw.githubusercontent.com/leptos-rs/leptos/main/examples/counter/public/favicon.ico > public/favicon.ico

    Let's create a tauri configuration file.

    sh
    touch src-tauri/taur.conf.json

    And drop this in there

    json
    {
      "identifier": "leptos.chat.app",
      "productName": "leptos_tauri_from_scratch",
      "version": "0.1.0",
      "build": {
        "beforeDevCommand": "",
        "beforeBuildCommand": "trunk build --no-default-features -v --features \"csr\"",
        "devUrl": "http://127.0.0.1:3000",
        "frontendDist": "../dist"
      },
      "bundle": {
        "active": true,
        "category": "DeveloperTool",
        "copyright": "",
        "externalBin": [],
        "icon": ["icons/icon.png"],
        "longDescription": "",
        "macOS": {
          "entitlements": null,
          "exceptionDomain": "",
          "frameworks": [],
          "providerShortName": null,
          "signingIdentity": null
        },
        "resources": [],
        "shortDescription": "",
        "targets": "all",
        "windows": {
          "certificateThumbprint": null,
          "digestAlgorithm": "sha256",
          "timestampUrl": ""
        }
      },
      "app": {
        "security": {
          "csp": null
        },
        "windows": [
          {
            "fullscreen": false,
            "height": 800,
            "resizable": true,
            "title": "LeptosChatApp",
            "width": 1200
          }
        ]
      }
    }

    You can basically ignore all of this except for

    json
    "build": {
        "beforeDevCommand": "",
        "beforeBuildCommand": "trunk build --no-default-features -v --features \"csr\"",
        "devUrl": "http://127.0.0.1:3000",
        "frontendDist": "../dist"
      },

    Let's look at

    json
    "beforeBuildCommand": "trunk build --no-default-features -v --features \"csr\"",

    When we cargo tauri build this will run before hand. Trunk will run it's build process, using the index.html file in the src-orig that we specified in Trunk.toml.

    We'll build a binary using only the CSR feature. This is important.

    We are going to build an SSR app, and serve it over the internet but we are also going to build a tauri client for desktop and mobile using CSR.

    It's going to make network requests to our server that is servering our app to browsers using SSR.

    This is the best of both worlds, we get the SEO of SSR and other advantages while being able to use CSR to build our app for other platforms.

    json
    "devUrl": "http://127.0.0.1:3000",
        "frontendDist": "../dist"

    Check https://tauri.app/v1/api/config/#buildconfig for what these do, but our before build command trunk build will build into a folder src-orig/dist which we reference here.

    Let's add a `Cargo.toml`` to both of our packages.

    sh
    touch src-tauri/Cargo.toml && touch src-orig/Cargo.toml

    Let's change src-tauri/Cargo.toml to this.

    toml
    [package]
    name = "src_tauri"
    version = "0.0.1"
    edition = "2021"
    
    [lib]
    name = "app_lib"
    path = "src/lib.rs"
    
    [build-dependencies]
    tauri-build = { version = "2.2.0", features = [] }
    
    [dependencies]
    log = "0.4.22"
    serde = { version = "1.0", features = ["derive"] }
    tauri = { version = "2.5.1", features = ["devtools"] }
    tauri-plugin-http = "2.4.4"
    
    [features]
    #default = ["custom-protocol"]
    custom-protocol = ["tauri/custom-protocol"]

    To make use of cargo tauri build we need tauri-build and we also need a build.rs.

    sh
    touch src-tauri/build.rs

    And let's change that to

    rust
    fn main() {
        tauri_build::build();
    }

    In our src-orig/Cargo.toml let's add.

    text
    /* Detailed source-code truncated for AI context efficiency. */

    So this looks like a normal SSR leptos, except for our CSR, Hydrate, and SSR versions.

    toml
    csr = ["leptos/csr", "dep:server_fn"]
    hydrate = [
      "leptos/hydrate",
      "dep:leptos_meta",
      "dep:console_error_panic_hook",
      "dep:wasm-bindgen"
    ]
    ssr = [

    also our binary is specified and named

    toml
    [[bin]]
    name="leptos_tauri_from_scratch_bin"
    path="./src/main.rs"

    our lib is specified, but unnamed (it will default to the project name in cargo leptos and in cargo tauri). We need the different crate types for cargo leptos serve and cargo tauri build

    toml
    [lib]
    crate-type = ["staticlib", "cdylib", "rlib"]

    We've added the override to our cargo leptos metadata.

    toml
    [package.metadata.leptos]
    bin-exe-name="leptos_tauri_from_scratch_bin"

    Our tauri app is going to send server function calls to this address, this is where we'll serve our hydratable SSR client from.

    toml
    site-addr = "0.0.0.0:3000"

    Now let's create the main.rs that we reference in the src-orig/Cargo.toml

    sh
    mkdir src-orig/src && touch src-orig/src/main.rs

    and drop this in there...

    text
    /* Detailed source-code truncated for AI context efficiency. */

    and the hydration at src-orig/src/lib.rs

    rust
    pub mod app;
    #[cfg(feature = "ssr")]
    pub mod fallback;
    
    #[cfg(feature = "hydrate")]
    #[wasm_bindgen::prelude::wasm_bindgen]
    pub fn hydrate() {
        console_error_panic_hook::set_once();
        leptos::mount::hydrate_body(app::App);
    }

    This is our three pronged binary.

    When we run cargo leptos server, we're going to get a server that is what's under #[cfg(feature="ssr")].

    And our csr feature

    rust
    #[cfg(feature = "csr")]
    pub fn main() {
        server_fn::client::set_server_url("http://127.0.0.1:3000");
        leptos::mount::mount_to_body(leptos_tauri_from_scratch::app::App);
    }

    Here we're setting the server functions to use the url base that we access in our browser. I.e local host, on the port we specified in the leptos metadata.
    Otherwise our tauri app will try to route server function network requests using it's own idea of what it's url is. Which is tauri://localhost on macOS, and something else on windows.

    Since we are going to be getting API requests from different locations beside our server's domain let's set up CORS, if you don't do this your tauri apps won't be able to make server function calls because it will run into CORS erros.

    rust
    let cors = CorsLayer::new()
                .allow_methods([axum::http::Method::GET, axum::http::Method::POST])
                .allow_origin(
                    "tauri://localhost"
                        .parse::<axum::http::HeaderValue>()
                        .unwrap(),
                )
                .allow_headers(vec![axum::http::header::CONTENT_TYPE]);

    If you are on windows the origin of your app will be different than tauri://localhost and you'll need to figure that out, as well as if you deploy it to places that aren't your localhost!

    Everything else is standard leptos, so let's fill in the fallback and the lib really quick.

    sh
    touch src-orig/src/lib.rs && touch src-orig/src/fallback.rs

    Let's dump this bog standard leptos code in the src-orig/src/app.rs

    rust
    use leptos::prelude::*;
    
    #[cfg(feature = "ssr")]
    pub fn shell(options: LeptosOptions) -> impl IntoView {
        use leptos_meta::MetaTags;
        view! {
            <!DOCTYPE html>
            <html lang="en">
                <head>
                    <meta charset="utf-8"/>
                    <meta name="viewport" content="width=device-width, initial-scale=1"/>
                    <AutoReload options=options.clone() />
                    <HydrationScripts options/>
                    <MetaTags/>
                </head>
                <body>
                    <App/>
                </body>
            </html>
        }
    }
    
    #[server(endpoint = "hello_world")]
    pub async fn hello_world_server() -> Result<String, ServerFnError> {
        Ok("Hey.".to_string())
    }
    
    #[component]
    pub fn App() -> impl IntoView {
        let action = ServerAction::<HelloWorldServer>::new();
        let vals = RwSignal::new(String::new());
        Effect::new(move |_| {
            if let Some(resp) = action.value().get() {
                match resp {
                    Ok(val) => vals.set(val),
                    Err(err) => vals.set(format!("{err:?}")),
                }
            }
        });
    
        view! {
            <button
                on:click=move |_| {
                    action.dispatch(HelloWorldServer{});
                }
            >"Hello world."</button>
            <br/><br/>
            <span>"Server says: "</span>
            {move || vals.get()}
        }
    }

    and add this to src-org/src/fallback.rs

    rust
    use axum::{
        body::Body,
        extract::State,
        http::{Request, Response, StatusCode, Uri},
        response::{IntoResponse, Response as AxumResponse},
    };
    use leptos::{view, prelude::LeptosOptions};
    use tower::ServiceExt;
    use tower_http::services::ServeDir;
    
    pub async fn file_and_error_handler(
        uri: Uri,
        State(options): State<LeptosOptions>,
        req: Request<Body>,
    ) -> AxumResponse {
        let root = options.site_root.clone();
        let res = get_static_file(uri.clone(), &root).await.unwrap();
    
        if res.status() == StatusCode::OK {
            res.into_response()
        } else {
            let handler = leptos_axum::render_app_to_stream(
                move || view! {404},
            );
            handler(req).await.into_response()
        }
    }
    
    async fn get_static_file(
        uri: Uri,
        root: &str,
    ) -> Result<Response<Body>, (StatusCode, String)> {
        let req = Request::builder()
            .uri(uri.clone())
            .body(Body::empty())
            .unwrap();
        match ServeDir::new(root).oneshot(req).await {
            Ok(res) => Ok(res.into_response()),
            Err(err) => Err((
                StatusCode::INTERNAL_SERVER_ERROR,
                format!("Something went wrong: {err}"),
            )),
        }
    }

    Let's fill in our src-tauri/src/ folder.

    sh
    mkdir src-tauri/src && touch src-tauri/src/main.rs && touch src-tauri/src/lib.rs

    and drop this in src-tauri/src/main.rs This is standard tauri boilerplate.

    rust
    // Prevents additional console window on Windows in release, DO NOT REMOVE!!
    #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
    
    fn main() {
        app_lib::run();
    }

    and in src-tauri/src/lib.rs

    rust
    use tauri::Manager;
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
        tauri::Builder::default()
            .plugin(tauri_plugin_http::init())
            .setup(|app| {
                {
                    let window = app.get_webview_window("main").unwrap();
                    window.open_devtools();
                }
                Ok(())
            })
            .run(tauri::generate_context!())
            .expect("error while running tauri application");
    }

    We're gonna open devtools right away to see what is going on in our app. We need the tauri_http_plugin to make http calls, and generate_context reads our tauri.conf.json in the package in which its run.

    We need an icon folder and an icon to build.

    sh
    mkdir src-tauri/icons
    curl https://raw.githubusercontent.com/tauri-apps/tauri/dev/examples/.icons/128x128.png > src-tauri/icons/icon.png

    set nightly

    sh
    rustup override set nightly

    Then run

    sh
    cargo leptos serve

    You should get something like

    sh
    ➜  lepto_tauri_from_scratch git:(main) βœ— cargo leptos serve
        Finished dev [unoptimized + debuginfo] target(s) in 0.60s
           Cargo finished cargo build --package=leptos_tauri_from_scratch --lib --target-dir=/Users/sam/Projects/lepto_tauri_from_scratch/target/front --target=wasm32-unknown-unknown --no-default-features --features=hydrate
           Front compiling WASM
        Finished dev [unoptimized + debuginfo] target(s) in 0.93s
           Cargo finished cargo build --package=leptos_tauri_from_scratch --bin=leptos_tauri_from_scratch_bin --no-default-features --features=ssr
         Serving at http://0.0.0.0:3000
    listening on http://0.0.0.0:3000

    Now open a new terminal and

    sh
    cargo tauri build

    Install tauri-cli if you haven't already.

    It'll build with csr before

    sh
    Running beforeBuildCommand `trunk build --no-default-features -v --features "csr"`

    and then you should have your app, I'm on macOS so here's what I get. It's for desktop.

    sh
    Compiling src_tauri v0.0.1 (/Users/sam/Projects/lepto_tauri_from_scratch/src-tauri)
        Finished release [optimized] target(s) in 2m 26s
        Bundling leptos_tauri_from_scratch.app (/Users/sam/Projects/lepto_tauri_from_scratch/target/release/bundle/macos/leptos_tauri_from_scratch.app)
        Bundling leptos_tauri_from_scratch_0.1.0_x64.dmg (/Users/sam/Projects/lepto_tauri_from_scratch/target/release/bundle/dmg/leptos_tauri_from_scratch_0.1.0_x64.dmg)
        Running bundle_dmg.sh

    Open run it and voilΓ‘. Click hello world button and read "Hey" from the server.

    Thoughts, Feedback, Criticism, Comments?

    Send me any of the above, I'm @sjud on leptos discord. I'm always looking to improve and make these projects more helpful for the community. So please let me know how I can do that. Thanks!


    Overview (`examples/islands_router/e2e/README.md`)

    islands_router e2e tests

    Playwright tests for the islands router's client-side navigation, including
    regression coverage for navigating away from the Home route, whose <Title/>
    metadata component renders no element in the route body.

    Running

    Serve the example (from the example root):

    sh
    cargo leptos serve

    Then, in this directory:

    sh
    npm install
    npx playwright install chromium
    npx playwright test

    Overview (`examples/lazy_routes/e2e/README.md`)

    Lazy Routes

    This example demonstrates how to split the WASM bundle that is sent to the client into multiple binaries, which can be lazy-loaded, either independently or in a way that's integrated into the router.

    Without code splitting, the entire application is compiled to a monolithic WASM binary, the size of which grows in proportion to the complexity of the application. This means that the time to interactive (TTI) for any page is proportional to the size of the entire application, not only that page.

    Code splitting allows you to lazy-load some functions, by splitting off the WASM binary code for certain functions into separate files, which can be downloaded as needed. This minimizes initial TTI for any page, and then amortizes the cost of loading the binary over the lifetime of the application session.

    In many cases, this can be done with minimal or no cost.

    Lazy loading can be used in two ways, each of which is shown in the example.

    `#[lazy]` macro

    #[lazy] is an attribute macro that can be used to annotate an async fn in order to split its code out into a separate file that will be loaded on demand, when compiled with cargo leptos --split.

    This has some limitations (for example, it must return concrete types) but can be used for most functions.

    `LazyRoute`

    LazyRoute is a specialized application of #[lazy] that allows you to define an entire route/page of your application as being lazy-loaded.

    Creating a lazy route requires you to split the route into two parts:

    1. data(): A synchronous method that should be used to start loading any async data used by the page, for example by creating a Resource
    2. view(): An async (because lazy-loaded) method that renders the view.

    The purpose of splitting these into two parts is to avoid a β€œwaterfall,” in which the browser first waits for a lazy-loaded WASM chunk that defines the page, then makes a second request to the server to load the relevant data. Instead, a LazyRoute will begin loading resources created in the data method while lazy-loading the component body in the view, then render the route.

    This means that in many cases, the data loading β€œhides” the cost of the lazy-loading; i.e., the page needs to wait for the data to load, so the fact that it is waiting concurrently for the lazy-loaded view means that the lazy loading does not cost anything additional in terms of page load time.


    Overview (`examples/regression/e2e/README.md`)

    E2E Testing

    This example demonstrates e2e testing with Rust using executable requirements.

    Testing Stack

    Role Description
    Cucumber Test Runner Run Gherkin specifications as Rust tests
    Fantoccini Browser Client Interact with web pages through WebDriver
    Cargo Leptos Build Tool Compile example and start the server and end-2-end tests
    chromedriver WebDriver Provide WebDriver for Chrome

    Testing Organization

    Testing is organized around what a user can do and see/not see. Test scenarios are grouped by the user action and the object of that action. This makes it easier to locate and reason about requirements.

    Here is a brief overview of how things fit together.

    bash
    features
    └── {action}_{object}.feature   # Specify test scenarios
    tests
    β”œβ”€β”€ fixtures
    β”‚   β”œβ”€β”€ action.rs               # Perform a user action (click, type, etc.)
    β”‚   β”œβ”€β”€ check.rs                # Assert what a user can see/not see
    β”‚   β”œβ”€β”€ find.rs                 # Query page elements
    β”‚   β”œβ”€β”€ mod.rs
    β”‚   └── world
    β”‚       β”œβ”€β”€ action_steps.rs     # Map Gherkin steps to user actions
    β”‚       β”œβ”€β”€ check_steps.rs      # Map Gherkin steps to user expectations
    β”‚       └── mod.rs
    └── app_suite.rs                # Test main

    Overview (`examples/suspense_tests/e2e/README.md`)

    E2E Testing

    This example demonstrates e2e testing with Rust using executable requirements.

    Testing Stack

    Role Description
    Cucumber Test Runner Run Gherkin specifications as Rust tests
    Fantoccini Browser Client Interact with web pages through WebDriver
    Cargo Leptos Build Tool Compile example and start the server and end-2-end tests
    chromedriver WebDriver Provide WebDriver for Chrome

    Testing Organization

    Testing is organized around what a user can do and see/not see. Test scenarios are grouped by the user action and the object of that action. This makes it easier to locate and reason about requirements.

    Here is a brief overview of how things fit together.

    bash
    features
    └── {action}_{object}.feature   # Specify test scenarios
    tests
    β”œβ”€β”€ fixtures
    β”‚   β”œβ”€β”€ action.rs               # Perform a user action (click, type, etc.)
    β”‚   β”œβ”€β”€ check.rs                # Assert what a user can see/not see
    β”‚   β”œβ”€β”€ find.rs                 # Query page elements
    β”‚   β”œβ”€β”€ mod.rs
    β”‚   └── world
    β”‚       β”œβ”€β”€ action_steps.rs     # Map Gherkin steps to user actions
    β”‚       β”œβ”€β”€ check_steps.rs      # Map Gherkin steps to user expectations
    β”‚       └── mod.rs
    └── app_suite.rs                # Test main

    Overview (`examples/todo_app_sqlite/e2e/README.md`)

    E2E Testing

    This example demonstrates e2e testing with Rust using executable requirements.

    Testing Stack

    Role Description
    Cucumber Test Runner Run Gherkin specifications as Rust tests
    Fantoccini Browser Client Interact with web pages through WebDriver
    Cargo Leptos Build Tool Compile example and start the server and end-2-end tests
    chromedriver WebDriver Provide WebDriver for Chrome

    Testing Organization

    Testing is organized around what a user can do and see/not see. Test scenarios are grouped by the user action and the object of that action. This makes it easier to locate and reason about requirements.

    Here is a brief overview of how things fit together.

    bash
    features
    └── {action}_{object}.feature   # Specify test scenarios
    tests
    β”œβ”€β”€ fixtures
    β”‚   β”œβ”€β”€ action.rs               # Perform a user action (click, type, etc.)
    β”‚   β”œβ”€β”€ check.rs                # Assert what a user can see/not see
    β”‚   β”œβ”€β”€ find.rs                 # Query page elements
    β”‚   β”œβ”€β”€ mod.rs
    β”‚   └── world
    β”‚       β”œβ”€β”€ action_steps.rs     # Map Gherkin steps to user actions
    β”‚       β”œβ”€β”€ check_steps.rs      # Map Gherkin steps to user expectations
    β”‚       └── mod.rs
    └── app_suite.rs                # Test main

    Overview (`examples/todo_app_sqlite_axum/e2e/README.md`)

    E2E Testing

    This example demonstrates e2e testing with Rust using executable requirements.

    Testing Stack

    Role Description
    Cucumber Test Runner Run Gherkin specifications as Rust tests
    Fantoccini Browser Client Interact with web pages through WebDriver
    Cargo Leptos Build Tool Compile example and start the server and end-2-end tests
    chromedriver WebDriver Provide WebDriver for Chrome

    Testing Organization

    Testing is organized around what a user can do and see/not see. Test scenarios are grouped by the user action and the object of that action. This makes it easier to locate and reason about requirements.

    Here is a brief overview of how things fit together.

    bash
    features
    └── {action}_{object}.feature   # Specify test scenarios
    tests
    β”œβ”€β”€ fixtures
    β”‚   β”œβ”€β”€ action.rs               # Perform a user action (click, type, etc.)
    β”‚   β”œβ”€β”€ check.rs                # Assert what a user can see/not see
    β”‚   β”œβ”€β”€ find.rs                 # Query page elements
    β”‚   β”œβ”€β”€ mod.rs
    β”‚   └── world
    β”‚       β”œβ”€β”€ action_steps.rs     # Map Gherkin steps to user actions
    β”‚       β”œβ”€β”€ check_steps.rs      # Map Gherkin steps to user expectations
    β”‚       └── mod.rs
    └── app_suite.rs                # Test main

    Overview (`examples/todo_app_sqlite_csr/e2e/README.md`)

    E2E Testing

    This example demonstrates e2e testing with Rust using executable requirements.

    Testing Stack

    Role Description
    Cucumber Test Runner Run Gherkin specifications as Rust tests
    Fantoccini Browser Client Interact with web pages through WebDriver
    Cargo Leptos Build Tool Compile example and start the server and end-2-end tests
    chromedriver WebDriver Provide WebDriver for Chrome

    Testing Organization

    Testing is organized around what a user can do and see/not see. Test scenarios are grouped by the user action and the object of that action. This makes it easier to locate and reason about requirements.

    Here is a brief overview of how things fit together.

    bash
    features
    └── {action}_{object}.feature   # Specify test scenarios
    tests
    β”œβ”€β”€ fixtures
    β”‚   β”œβ”€β”€ action.rs               # Perform a user action (click, type, etc.)
    β”‚   β”œβ”€β”€ check.rs                # Assert what a user can see/not see
    β”‚   β”œβ”€β”€ find.rs                 # Query page elements
    β”‚   β”œβ”€β”€ mod.rs
    β”‚   └── world
    β”‚       β”œβ”€β”€ action_steps.rs     # Map Gherkin steps to user actions
    β”‚       β”œβ”€β”€ check_steps.rs      # Map Gherkin steps to user expectations
    β”‚       └── mod.rs
    └── app_suite.rs                # Test main

    Overview (`examples/websocket/e2e/README.md`)

    E2E Testing

    This example demonstrates e2e testing with Rust using executable requirements.

    Testing Stack

    Role Description
    Cucumber Test Runner Run Gherkin specifications as Rust tests
    Fantoccini Browser Client Interact with web pages through WebDriver
    Cargo Leptos Build Tool Compile example and start the server and end-2-end tests
    chromedriver WebDriver Provide WebDriver for Chrome

    Testing Organization

    Testing is organized around what a user can do and see/not see. Test scenarios are grouped by the user action and the object of that action. This makes it easier to locate and reason about requirements.

    Here is a brief overview of how things fit together.

    bash
    features
    └── {action}_{object}.feature   # Specify test scenarios
    tests
    β”œβ”€β”€ fixtures
    β”‚   β”œβ”€β”€ action.rs               # Perform a user action (click, type, etc.)
    β”‚   β”œβ”€β”€ check.rs                # Assert what a user can see/not see
    β”‚   β”œβ”€β”€ find.rs                 # Query page elements
    β”‚   β”œβ”€β”€ mod.rs
    β”‚   └── world
    β”‚       β”œβ”€β”€ action_steps.rs     # Map Gherkin steps to user actions
    β”‚       β”œβ”€β”€ check_steps.rs      # Map Gherkin steps to user expectations
    β”‚       └── mod.rs
    └── app_suite.rs                # Test main

    Overview (`projects/nginx-mpmc/app-1/README.md`)

    Leptos Axum Starter Template

    This is a template for use with the Leptos web framework and the cargo-leptos tool using Axum.

    Creating your template repo

    If you don't have cargo-leptos installed you can install it with

    bash
    cargo install cargo-leptos

    Then run

    bash
    cargo leptos new --git leptos-rs/start-axum

    to generate a new project template.

    bash
    cd app-1

    to go to your newly created project.
    Feel free to explore the project structure, but the best place to start with your application code is in src/app.rs.
    Addtionally, Cargo.toml may need updating as new versions of the dependencies are released, especially if things are not working after a cargo update.

    Running your project

    bash
    cargo leptos watch

    Installing Additional Tools

    By default, cargo-leptos uses nightly Rust, cargo-generate, and sass. If you run into any trouble, you may need to install one or more of these tools.

    1. rustup toolchain install nightly --allow-downgrade - make sure you have Rust nightly
    2. rustup target add wasm32-unknown-unknown - add the ability to compile Rust to WebAssembly
    3. cargo install cargo-generate - install cargo-generate binary (should be installed automatically in future)
    4. npm install sass - install dart-sass (should be optional in future

    Compiling for Release

    bash
    cargo leptos build --release

    Will generate your server binary in target/server/release and your site package in target/site

    Testing Your Project

    bash
    cargo leptos end-to-end
    bash
    cargo leptos end-to-end --release

    Cargo-leptos uses Playwright as the end-to-end test tool.
    Tests are located in end2end/tests directory.

    Executing a Server on a Remote Machine Without the Toolchain

    After running a cargo leptos build --release the minimum files needed are:

    1. The server binary located in target/server/release
    2. The site directory and all files within located in target/site

    Copy these files to your remote server. The directory structure should be:

    text
    app-1
    site/

    Set the following environment variables (updating for your project as needed):

    text
    LEPTOS_OUTPUT_NAME="app-1"
    LEPTOS_SITE_ROOT="site"
    LEPTOS_SITE_PKG_DIR="pkg"
    LEPTOS_SITE_ADDR="127.0.0.1:3000"
    LEPTOS_RELOAD_PORT="3001"

    Finally, run the server binary.


    Overview (`projects/nginx-mpmc/app-2/README.md`)

    Leptos Axum Starter Template

    This is a template for use with the Leptos web framework and the cargo-leptos tool using Axum.

    Creating your template repo

    If you don't have cargo-leptos installed you can install it with

    bash
    cargo install cargo-leptos

    Then run

    bash
    cargo leptos new --git leptos-rs/start-axum

    to generate a new project template.

    bash
    cd app-2

    to go to your newly created project.
    Feel free to explore the project structure, but the best place to start with your application code is in src/app.rs.
    Addtionally, Cargo.toml may need updating as new versions of the dependencies are released, especially if things are not working after a cargo update.

    Running your project

    bash
    cargo leptos watch

    Installing Additional Tools

    By default, cargo-leptos uses nightly Rust, cargo-generate, and sass. If you run into any trouble, you may need to install one or more of these tools.

    1. rustup toolchain install nightly --allow-downgrade - make sure you have Rust nightly
    2. rustup target add wasm32-unknown-unknown - add the ability to compile Rust to WebAssembly
    3. cargo install cargo-generate - install cargo-generate binary (should be installed automatically in future)
    4. npm install sass - install dart-sass (should be optional in future

    Compiling for Release

    bash
    cargo leptos build --release

    Will generate your server binary in target/server/release and your site package in target/site

    Testing Your Project

    bash
    cargo leptos end-to-end
    bash
    cargo leptos end-to-end --release

    Cargo-leptos uses Playwright as the end-to-end test tool.
    Tests are located in end2end/tests directory.

    Executing a Server on a Remote Machine Without the Toolchain

    After running a cargo leptos build --release the minimum files needed are:

    1. The server binary located in target/server/release
    2. The site directory and all files within located in target/site

    Copy these files to your remote server. The directory structure should be:

    text
    app-2
    site/

    Set the following environment variables (updating for your project as needed):

    text
    LEPTOS_OUTPUT_NAME="app-2"
    LEPTOS_SITE_ROOT="site"
    LEPTOS_SITE_PKG_DIR="pkg"
    LEPTOS_SITE_ADDR="127.0.0.1:3000"
    LEPTOS_RELOAD_PORT="3001"

    Finally, run the server binary.


    Overview (`projects/nginx-mpmc/shared-server-1/README.md`)

    Leptos Axum Starter Template

    This is a template for use with the Leptos web framework and the cargo-leptos tool using Axum.

    Creating your template repo

    If you don't have cargo-leptos installed you can install it with

    bash
    cargo install cargo-leptos

    Then run

    bash
    cargo leptos new --git leptos-rs/start-axum

    to generate a new project template.

    bash
    cd shared-server

    to go to your newly created project.
    Feel free to explore the project structure, but the best place to start with your application code is in src/app.rs.
    Addtionally, Cargo.toml may need updating as new versions of the dependencies are released, especially if things are not working after a cargo update.

    Running your project

    bash
    cargo leptos watch

    Installing Additional Tools

    By default, cargo-leptos uses nightly Rust, cargo-generate, and sass. If you run into any trouble, you may need to install one or more of these tools.

    1. rustup toolchain install nightly --allow-downgrade - make sure you have Rust nightly
    2. rustup target add wasm32-unknown-unknown - add the ability to compile Rust to WebAssembly
    3. cargo install cargo-generate - install cargo-generate binary (should be installed automatically in future)
    4. npm install sass - install dart-sass (should be optional in future

    Compiling for Release

    bash
    cargo leptos build --release

    Will generate your server binary in target/server/release and your site package in target/site

    Testing Your Project

    bash
    cargo leptos end-to-end
    bash
    cargo leptos end-to-end --release

    Cargo-leptos uses Playwright as the end-to-end test tool.
    Tests are located in end2end/tests directory.

    Executing a Server on a Remote Machine Without the Toolchain

    After running a cargo leptos build --release the minimum files needed are:

    1. The server binary located in target/server/release
    2. The site directory and all files within located in target/site

    Copy these files to your remote server. The directory structure should be:

    text
    shared-server
    site/

    Set the following environment variables (updating for your project as needed):

    text
    LEPTOS_OUTPUT_NAME="shared-server"
    LEPTOS_SITE_ROOT="site"
    LEPTOS_SITE_PKG_DIR="pkg"
    LEPTOS_SITE_ADDR="127.0.0.1:3000"
    LEPTOS_RELOAD_PORT="3001"

    Finally, run the server binary.


    Overview (`projects/nginx-mpmc/shared-server-2/README.md`)

    Leptos Axum Starter Template

    This is a template for use with the Leptos web framework and the cargo-leptos tool using Axum.

    Creating your template repo

    If you don't have cargo-leptos installed you can install it with

    bash
    cargo install cargo-leptos

    Then run

    bash
    cargo leptos new --git leptos-rs/start-axum

    to generate a new project template.

    bash
    cd shared-server

    to go to your newly created project.
    Feel free to explore the project structure, but the best place to start with your application code is in src/app.rs.
    Addtionally, Cargo.toml may need updating as new versions of the dependencies are released, especially if things are not working after a cargo update.

    Running your project

    bash
    cargo leptos watch

    Installing Additional Tools

    By default, cargo-leptos uses nightly Rust, cargo-generate, and sass. If you run into any trouble, you may need to install one or more of these tools.

    1. rustup toolchain install nightly --allow-downgrade - make sure you have Rust nightly
    2. rustup target add wasm32-unknown-unknown - add the ability to compile Rust to WebAssembly
    3. cargo install cargo-generate - install cargo-generate binary (should be installed automatically in future)
    4. npm install sass - install dart-sass (should be optional in future

    Compiling for Release

    bash
    cargo leptos build --release

    Will generate your server binary in target/server/release and your site package in target/site

    Testing Your Project

    bash
    cargo leptos end-to-end
    bash
    cargo leptos end-to-end --release

    Cargo-leptos uses Playwright as the end-to-end test tool.
    Tests are located in end2end/tests directory.

    Executing a Server on a Remote Machine Without the Toolchain

    After running a cargo leptos build --release the minimum files needed are:

    1. The server binary located in target/server/release
    2. The site directory and all files within located in target/site

    Copy these files to your remote server. The directory structure should be:

    text
    shared-server
    site/

    Set the following environment variables (updating for your project as needed):

    text
    LEPTOS_OUTPUT_NAME="shared-server"
    LEPTOS_SITE_ROOT="site"
    LEPTOS_SITE_PKG_DIR="pkg"
    LEPTOS_SITE_ADDR="127.0.0.1:3000"
    LEPTOS_RELOAD_PORT="3001"

    Finally, run the server binary.


    Overview (`docs/book/src/async/README.md`)


    Overview (`docs/book/src/deployment/README.md`)


    Overview (`docs/book/src/getting_started/README.md`)


    Overview (`docs/book/src/progressive_enhancement/README.md`)


    Overview (`docs/book/src/reactivity/README.md`)


    Overview (`docs/book/src/router/README.md`)


    Overview (`docs/book/src/server/README.md`)


    Overview (`docs/book/src/ssr/README.md`)


    Overview (`docs/book/src/view/README.md`)


    Overview (`docs/book_ru/src/async/README.md`)


    Overview (`docs/book_ru/src/deployment/README.md`)


    Overview (`docs/book_ru/src/getting_started/README.md`)


    Overview (`docs/book_ru/src/progressive_enhancement/README.md`)


    Overview (`docs/book_ru/src/reactivity/README.md`)


    Overview (`docs/book_ru/src/router/README.md`)


    Overview (`docs/book_ru/src/server/README.md`)


    Overview (`docs/book_ru/src/ssr/README.md`)


    Overview (`docs/book_ru/src/view/README.md`)


    COMMON BUGS (`docs/COMMON_BUGS.md`)

    Leptos Gotchas: Common Bugs

    This document is intended as a running list of common issues, with example code and solutions.

    Reactivity

    Avoid writing to a signal from an effect

    Issue: Sometimes you want to update a reactive signal in a way that depends on another signal.

    rust
    let (a, set_a) = signal(0);
    let (b, set_b) = signal(false);
    
    Effect::new(move |_| {
    	if a.get() > 5 {
    		set_b.set(true);
    	}
    });

    This creates an inefficient chain of updates, and can easily lead to infinite loops in more complex applications.

    Solution: Follow the rule, What can be derived, should be derived. In this case, this has the benefit of massively reducing the code size, too!

    rust
    let (a, set_a) = signal(0);
    let b = move || a.get() > 5;

    Templates and the DOM

    `` doesn't update or stops updating

    Many DOM attributes can be updated either by setting an attribute on the DOM node, or by setting an object property directly on it. In general, setAttribute() stops working once the property has been set.

    This means that in practice, attributes like value or checked on an element only update the _default_ value for the. If you want to reactively update the value, you should use prop:value instead to set the value property.

    rust
    let (a, set_a) = signal("Starting value".to_string());
    let on_input = move |ev| set_a.set(event_target_value(&ev));
    
    view! {
    
    	// ❌ reactivity doesn't work as expected: typing only updates the default
    	//    of each input, so if you start typing in the second input, it won't
    	//    update the first one
    	<input value=a on:input=on_input />
    	<input value=a on:input=on_input />
    }
    rust
    let (a, set_a) = signal("Starting value".to_string());
    let on_input = move |ev| set_a.set(event_target_value(&ev));
    
    view! {
    
    	// βœ… works as intended by setting the value *property*
    	<input prop:value=a on:input=on_input />
    	<input prop:value=a on:input=on_input />
    }

    Build configuration

    Cargo feature resolution in workspaces

    A new version of Cargo's feature resolver was introduced for the 2021 edition of Rust.
    For single crate projects it will select a resolver version based on the Rust edition in Cargo.toml. As there is no Rust edition present for Cargo.toml in a workspace, Cargo will default to the pre 2021 edition resolver.
    This can cause issues resulting in non WASM compatible code being built for a WASM target. Seeing mio failing to build is often a sign that none WASM compatible code is being included in the build.

    The resolver version can be set in the workspace Cargo.toml to remedy this issue.

    toml
    [workspace]
    members = ["member1", "member2"]
    resolver = "2"

    Book Src 01 Introduction (`docs/book/src/01_introduction.md`)


    Book Src 15 Global State (`docs/book/src/15_global_state.md`)


    Book Src SUMMARY (`docs/book/src/SUMMARY.md`)

    Summary


    Book Src Appendix Reactive Graph (`docs/book/src/appendix_reactive_graph.md`)


    Book Src Csr Wrapping Up (`docs/book/src/csr_wrapping_up.md`)


    Book Src Interlude Projecting Children (`docs/book/src/interlude_projecting_children.md`)


    Book Src Interlude Styling (`docs/book/src/interlude_styling.md`)


    Book Src Islands (`docs/book/src/islands.md`)


    Book Src Metadata (`docs/book/src/metadata.md`)


    Book Src Testing (`docs/book/src/testing.md`)


    Book Ru Src 01 Introduction (`docs/book_ru/src/01_introduction.md`)


    Book Ru Src 15 Global State (`docs/book_ru/src/15_global_state.md`)


    Book Ru Src SUMMARY (`docs/book_ru/src/SUMMARY.md`)

    ОглавлСниС


    Book Ru Src Appendix Reactive Graph (`docs/book_ru/src/appendix_reactive_graph.md`)


    Book Ru Src Csr Wrapping Up (`docs/book_ru/src/csr_wrapping_up.md`)


    Book Ru Src Interlude Projecting Children (`docs/book_ru/src/interlude_projecting_children.md`)


    Book Ru Src Interlude Styling (`docs/book_ru/src/interlude_styling.md`)


    Book Ru Src Islands (`docs/book_ru/src/islands.md`)


    Book Ru Src Metadata (`docs/book_ru/src/metadata.md`)


    Book Ru Src Testing (`docs/book_ru/src/testing.md`)


    Book Src Async 10 Resources (`docs/book/src/async/10_resources.md`)


    Book Src Async 11 Suspense (`docs/book/src/async/11_suspense.md`)


    Book Src Async 12 Transition (`docs/book/src/async/12_transition.md`)


    Book Src Async 13 Actions (`docs/book/src/async/13_actions.md`)


    Book Src Deployment Binary Size (`docs/book/src/deployment/binary_size.md`)


    Book Src Getting Started Community Crates (`docs/book/src/getting_started/community_crates.md`)


    Book Src Getting Started Leptos Dx (`docs/book/src/getting_started/leptos_dx.md`)


    Book Src Progressive Enhancement Action Form (`docs/book/src/progressive_enhancement/action_form.md`)


    Book Src Reactivity 14 Create Effect (`docs/book/src/reactivity/14_create_effect.md`)


    Book Src Reactivity Interlude Functions (`docs/book/src/reactivity/interlude_functions.md`)


    Book Src Reactivity Working With Signals (`docs/book/src/reactivity/working_with_signals.md`)


    Book Src Router 16 Routes (`docs/book/src/router/16_routes.md`)


    Book Src Router 17 Nested Routing (`docs/book/src/router/17_nested_routing.md`)


    Book Src Router 18 Params And Queries (`docs/book/src/router/18_params_and_queries.md`)


    Book Src Router 19 A (`docs/book/src/router/19_a.md`)


    Book Src Router 20 Form (`docs/book/src/router/20_form.md`)


    Book Src Server 25 Server Functions (`docs/book/src/server/25_server_functions.md`)


    Book Src Server 26 Extractors (`docs/book/src/server/26_extractors.md`)


    Book Src Server 27 Response (`docs/book/src/server/27_response.md`)


    Book Src Ssr 21 Cargo Leptos (`docs/book/src/ssr/21_cargo_leptos.md`)


    Book Src Ssr 22 Life Cycle (`docs/book/src/ssr/22_life_cycle.md`)


    Book Src Ssr 23 Ssr Modes (`docs/book/src/ssr/23_ssr_modes.md`)


    Book Src Ssr 24 Hydration Bugs (`docs/book/src/ssr/24_hydration_bugs.md`)


    Book Src View 01 Basic Component (`docs/book/src/view/01_basic_component.md`)


    Book Src View 02 Dynamic Attributes (`docs/book/src/view/02_dynamic_attributes.md`)


    Book Src View 03 Components (`docs/book/src/view/03_components.md`)


    Book Src View 04 Iteration (`docs/book/src/view/04_iteration.md`)


    Book Src View 04b Iteration (`docs/book/src/view/04b_iteration.md`)


    Book Src View 05 Forms (`docs/book/src/view/05_forms.md`)


    Book Src View 06 Control Flow (`docs/book/src/view/06_control_flow.md`)


    Book Src View 07 Errors (`docs/book/src/view/07_errors.md`)


    Book Src View 08 Parent Child (`docs/book/src/view/08_parent_child.md`)


    Book Src View 09 Component Children (`docs/book/src/view/09_component_children.md`)


    Book Src View Builder (`docs/book/src/view/builder.md`)


    Book Ru Src Async 10 Resources (`docs/book_ru/src/async/10_resources.md`)


    Book Ru Src Async 11 Suspense (`docs/book_ru/src/async/11_suspense.md`)


    Book Ru Src Async 12 Transition (`docs/book_ru/src/async/12_transition.md`)


    Book Ru Src Async 13 Actions (`docs/book_ru/src/async/13_actions.md`)


    Book Ru Src Deployment Binary Size (`docs/book_ru/src/deployment/binary_size.md`)


    Book Ru Src Getting Started Community Crates (`docs/book_ru/src/getting_started/community_crates.md`)


    Book Ru Src Getting Started Leptos Dx (`docs/book_ru/src/getting_started/leptos_dx.md`)


    Book Ru Src Progressive Enhancement Action Form (`docs/book_ru/src/progressive_enhancement/action_form.md`)


    Book Ru Src Reactivity 14 Create Effect (`docs/book_ru/src/reactivity/14_create_effect.md`)


    Book Ru Src Reactivity Interlude Functions (`docs/book_ru/src/reactivity/interlude_functions.md`)


    Book Ru Src Reactivity Working With Signals (`docs/book_ru/src/reactivity/working_with_signals.md`)


    Book Ru Src Router 16 Routes (`docs/book_ru/src/router/16_routes.md`)


    Book Ru Src Router 17 Nested Routing (`docs/book_ru/src/router/17_nested_routing.md`)


    Book Ru Src Router 18 Params And Queries (`docs/book_ru/src/router/18_params_and_queries.md`)


    Book Ru Src Router 19 A (`docs/book_ru/src/router/19_a.md`)


    Book Ru Src Router 20 Form (`docs/book_ru/src/router/20_form.md`)


    Book Ru Src Server 25 Server Functions (`docs/book_ru/src/server/25_server_functions.md`)


    Book Ru Src Server 26 Extractors (`docs/book_ru/src/server/26_extractors.md`)


    Book Ru Src Server 27 Response (`docs/book_ru/src/server/27_response.md`)


    Book Ru Src Ssr 21 Cargo Leptos (`docs/book_ru/src/ssr/21_cargo_leptos.md`)


    Book Ru Src Ssr 22 Life Cycle (`docs/book_ru/src/ssr/22_life_cycle.md`)


    Book Ru Src Ssr 23 Ssr Modes (`docs/book_ru/src/ssr/23_ssr_modes.md`)


    Book Ru Src Ssr 24 Hydration Bugs (`docs/book_ru/src/ssr/24_hydration_bugs.md`)


    Book Ru Src View 01 Basic Component (`docs/book_ru/src/view/01_basic_component.md`)


    Book Ru Src View 02 Dynamic Attributes (`docs/book_ru/src/view/02_dynamic_attributes.md`)


    Book Ru Src View 03 Components (`docs/book_ru/src/view/03_components.md`)


    Book Ru Src View 04 Iteration (`docs/book_ru/src/view/04_iteration.md`)


    Book Ru Src View 04b Iteration (`docs/book_ru/src/view/04b_iteration.md`)


    Book Ru Src View 05 Forms (`docs/book_ru/src/view/05_forms.md`)


    Book Ru Src View 06 Control Flow (`docs/book_ru/src/view/06_control_flow.md`)


    Book Ru Src View 07 Errors (`docs/book_ru/src/view/07_errors.md`)


    Book Ru Src View 08 Parent Child (`docs/book_ru/src/view/08_parent_child.md`)


    Book Ru Src View 09 Component Children (`docs/book_ru/src/view/09_component_children.md`)


    Book Ru Src View Builder (`docs/book_ru/src/view/builder.md`)


    --- METRICS ---