Announcing Sycamore v0.9.0
Reactivity v3, View v2, resources API and suspense, SSR streaming, attributes passthrough, new website, and more!
Sycamore is a next gen Rust web UI library powered by fine-grained reactivity.
Latest Release: v0.9.4
A minimal framework for Rust web apps, designed to keep boilerplate out of your way.
Fine-grained reactivity
Signals store reactive state. Memos track the signals they read and recompute when those dependencies change. Views subscribe to reactive values and update the corresponding DOM nodes without re-running the component function.
Read about reactive statelet mut count = create_signal(0);
let doubled = create_memo(move || count.get() * 2);
view! {
button(on_click=move |_| count += 1) {
"Count: {count}"
}
// Only this text updates when doubled changes.
p { "Doubled: {doubled}" }
}Type-checked UI
Built-in HTML elements have typed attributes, DOM properties, and event handlers checked by the Rust compiler. The view macro integrates with rust-analyzer for autocompletion, inline diagnostics, and go-to-definition as you write your UI.
Read about the view macrolet name = create_signal(String::new());
view! {
input(bind:value=name, placeholder="Your name")
button(
disabled=move || name.get_clone().is_empty(),
on_click=move |_| name.set(String::new()),
) {
"Clear"
}
p { "Hello, {name}!" }
}Server-side rendering
Sycamore is fully isomorphic: the same components can render on the server and in the browser. Build a client-rendered single-page app, or render HTML on the server and hydrate it on the client to attach reactive state and event handlers.
Read about server-side rendering#[component]
fn App() -> View {
view! {
h1 { "Hello from the server." }
}
}
let html = sycamore::render_to_string(App);Async and Suspense
Async components can await data before returning a view. A Suspense boundary renders its fallback while nested async components or resources are pending, then displays the resolved content.
Read about resources and Suspense#[component]
async fn Welcome() -> View {
// Your async data-loading function.
let name = fetch_name().await;
view! { p { "Welcome, {name}" } }
}
view! {
Suspense(fallback=|| view! { "Loading…" }) {
Welcome {}
}
}Built-in routing
Derive Route on a Rust enum to map URL paths to variants. Path parameters are parsed into typed fields, and a designated variant handles unmatched paths. The router supports both client-side navigation and server-side rendering.
Read about routinguse sycamore_router::Route;
#[derive(Route, Clone)]
enum AppRoutes {
#[to("/")]
Home,
#[to("/hello/<name>")]
Hello { name: String },
#[not_found]
NotFound,
}An open-source project built by people who use it. Join the conversation, contribute code, or support development.
Thanks to everyone who contributes code, improves the docs, and reports bugs. There are plenty of ways to get involved, whether you're new to Rust or already building with Sycamore.
You can also support Sycamore's ongoing development by sponsoring Luke, the project's creator and maintainer.
Sponsor on GitHubReleases, development updates, and notes from the Sycamore team.
Reactivity v3, View v2, resources API and suspense, SSR streaming, attributes passthrough, new website, and more!
Reactivity v2, better component props and children, async/await support, and more...
How the next version of Sycamore will be the most ergonomic yet.
Client-side hydration + Builder API
Faster and faster with plenty of fixes and features...
SSR + Routing