4 releases
Uses new Rust 2024
| 0.2.3 | Oct 4, 2025 |
|---|---|
| 0.2.2 | Oct 4, 2025 |
| 0.2.1 | Jul 20, 2025 |
| 0.2.0 | Jun 6, 2025 |
#2706 in Procedural macros
145 downloads per month
Used in 5 crates
(3 directly)
45KB
813 lines
Momenta
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>
}
}
Features
Element-Level Reactivity
Fine-grained reactivity that automatically tracks dependencies and updates only what has changed.
Type-Safe Components
Leverage Rust's type system for compile-time guarantees and better developer experience.
Lightweight & Fast
Small runtime with minimal overhead. Your apps stay fast and bundle sizes stay small.
Familiar API
Inspired by React with a Rust-first approach to reactive programming.
SSR Ready
Server-side rendering support out of the box with a simple API for better performance and SEO.
Composable Primitives
Build complex UIs from simple, reusable reactive primitives:
- Signals - Fine-grained reactive state
- Computed Signals - Derived values with automatic memoization
- Effects - Side effect management
- Resources - Async data loading with built-in loading/error states
Quick Start
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");
}
Why Momenta?
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:
- Simplicity - Easy to learn, easy to use
- Performance - Fine-grained reactivity means minimal updates
- Type Safety - Leverage Rust's type system for compile-time guarantees
- Familiarity - React-like API that's easy to pick up
Core Concepts
Signals - Reactive State
let count = create_signal(0);
count.set(5); // Set value
let value = count.get(); // Get value
count += 1; // Update with operators
Computed Signals - Derived Values
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);
Effects - Side Effects
create_effect(|| {
console::log!("Count changed to: {}", count.get());
});
Resources - Async Data
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>
}
Components - Reusable UI
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>
}
}
Control Flow - Conditionals & Lists
// 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>
}
Documentation
- Getting Started Guide - Learn the basics
- API Documentation - Complete API reference
Feature Flags
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"
Community & Support
- GitHub Discussions - Ask questions, share ideas
- Issues - Report bugs, request features
- Contributing Guide - Learn how to contribute
Contributing
We welcome contributions! Here's how you can help:
- Report bugs - Open an issue with a minimal reproduction
- Suggest features - Start a discussion about your idea
- Improve docs - Help us make the docs better
- Submit PRs - Fix bugs or implement features
Please read our Contributing Guide before submitting PRs.
Comparison with Other Frameworks
| 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 |
License
MIT License - see LICENSE for details
Dependencies
~2.1–3.5MB
~66K SLoC