| Crates.io | momenta |
| lib.rs | momenta |
| version | 0.2.3 |
| created_at | 2025-06-06 19:23:37.508645+00 |
| updated_at | 2025-10-04 20:51:55.36316+00 |
| description | A framework for building element level reactive ui |
| homepage | |
| repository | https://github.com/elcharitas/momenta |
| max_upload_size | |
| id | 1703362 |
| size | 22,639 |
Simple and performant reactivity for building user interfaces
A fine-grained reactive framework for Rust that makes it simple to build high-performance, reactive user interfaces using Rust's type system and ownership model.
use momenta::prelude::*;
#[component]
fn Counter() -> Node {
let count = create_signal(0);
rsx! {
<div class="counter">
<h1>"Count: " {count}</h1>
<button on:click={move |_| count += 1}>"Increment"</button>
</div>
}
}
Fine-grained reactivity that automatically tracks dependencies and updates only what has changed.
Leverage Rust's type system for compile-time guarantees and better developer experience.
Small runtime with minimal overhead. Your apps stay fast and bundle sizes stay small.
Inspired by React with a Rust-first approach to reactive programming.
Server-side rendering support out of the box with a simple API for better performance and SEO.
Build complex UIs from simple, reusable reactive primitives:
Add Momenta to your Cargo.toml:
[dependencies]
momenta = "0.2"
Create your first component:
use momenta::prelude::*;
#[component]
fn App() -> Node {
let count = create_signal(0);
rsx! {
<div>
<h1>"Counter: " {count}</h1>
<button on:click={move |_| count += 1}>
"Increment"
</button>
<button on:click={move |_| count -= 1}>
"Decrement"
</button>
</div>
}
}
fn main() {
momenta::dom::render_root::<App>("#app");
}
I started this project while attempting to transit my portfolio from Next.js to Rust. I tried using dioxus, yew, and hypertext, but I found them to be too complex and verbose for my needs. I wanted a simple and intuitive way to write HTML-like templates in Rust, while still leveraging the full power of Rust's type system.
Momenta aims to provide:
let count = create_signal(0);
count.set(5); // Set value
let value = count.get(); // Get value
count += 1; // Update with operators
let count = create_signal(0);
let doubled = create_computed(move || count.get() * 2);
// or use the derive method
let tripled = count.derive(|&n| n * 3);
create_effect(|| {
console::log!("Count changed to: {}", count.get());
});
let user = create_resource(|| async {
fetch_user_data().await
});
rsx! {
<div>
{when!(user.loading() => <p>"Loading..."</p>
else when!(user.error().is_some() => <p>"Error loading user"</p>)
else <p>"User: " {user.get().unwrap()}</p>)}
</div>
}
pub struct ButtonProps {
pub label: &'static str,
pub on_click: Box<dyn Fn()>,
}
#[component]
fn Button(props: &ButtonProps) -> Node {
rsx! {
<button on:click={move |_| (props.on_click)()}>
{props.label}
</button>
}
}
// Conditional rendering
{when!(show => <p>"Visible"</p> else <p>"Hidden"</p>)}
// List rendering
let items = create_signal(vec!["Apple", "Banana", "Cherry"]);
rsx! {
<ul>
{items.map(|item| rsx!(<li>{item}</li>))}
</ul>
}
Enable optional features in your Cargo.toml:
[dependencies]
momenta = { version = "0.2", features = ["full-reactivity"] }
Available features:
dom - All HTML elements with DOM rendering (default)wasm - WebAssembly support for browser rendering (default)computed - Computed signals supportmemoization - Memoization utilitiesfull-reactivity - All reactive features (includes computed + memoization, default)For server-side rendering without DOM, use only momenta-core:
[dependencies]
momenta-core = "0.2"
We welcome contributions! Here's how you can help:
Please read our Contributing Guide before submitting PRs.
| Feature | Momenta | Yew | Dioxus |
|---|---|---|---|
| Fine-grained reactivity | Yes | No | Yes |
| JSX-like syntax | Yes | Yes | Yes |
| SSR Support | Yes | Yes | Yes |
| Learning curve | Low | Medium | Medium |
| Bundle size | Small | Large | Medium |
MIT License - see LICENSE for details