A small beginning.
Build a server-rendered Rust page, then add local-first behavior where it matters.
Install from crates.io
Hearth 0.1.0 is available now. Create an app with the tested Rust 1.99.1 toolchain; no Node.js or pnpm is needed.
rustup toolchain install 1.99.1
cargo new my-hearth-app
cd my-hearth-app
rustup override set 1.99.1
cargo add hearth@=0.1.0
cargo add tokio --features rt-multi-thread,macros
cargo install hearth-cli --version 0.1.0 --lockedReplace src/main.rs with the first page below, then run cargo run --release. Open http://127.0.0.1:3000. For interactive pages, bundle assets from the same build as the binary.
Your first page
The hearth crate includes the router, views, reactive expressions, local-first tables and the application server.
use hearth::{Result, router::{module_router, page}, view::{View, view}};
#[tokio::main]
async fn main() {
hearth::start(module_router!().build()).await.unwrap();
}
#[page]
async fn home() -> Result<impl View> {
Ok(view! { <h1>"Hello from Hearth"</h1> })
}Explore the source
The public repository contains this website and the full issue tracker. These commands build the website from source; framework development uses pnpm 10.20.0.
git clone https://github.com/wbunting/hearth.git
cd hearth
pnpm install --frozen-lockfile
pnpm build:runtime
cargo build --release -p hearth-cli -p hearth-site
./target/release/hearth asset bundle --release -p hearth-site
PORT=3620 ./target/release/hearth-siteOpen http://localhost:3620. The site uses an in-memory SQLite database by default. Each browser gets its own demo rows; a server restart resets them.
From page to app
- Define a Toasty model and derive Table for its browser-facing row.
- Provide a read scope and explicitly allow writable fields.
- Use live_query! in a component, then render it with for row in $(query).
- Add runtime().assets(...) to the router and include runtime::script() in your page.
- Embed the client schema using json_script("hearth-boot", ...).
The complete, runnable examples are site/src and examples/hearth-tracker in the checkout. Authorize every table load and mutation; hiding a control is not access control.
Current boundaries
- Experimental API. Pin your dependency and expect breaking changes.
- Runtime expressions use a supported Rust vocabulary, not arbitrary Rust.
- The browser database is an indexed JavaScript store. It is not SQLite or a Rust WebAssembly runtime.
- IndexedDB caches server rows. Pending writes do not survive closing the tab.
- Delta sync scans scoped server tables. Measure with your own data volume.
- Strict CSP covers compiled expression paths. App-authored inline styles and arbitrary raw HTML streams need separate consideration.
Credits
Hearth is a fork of Topcoat v0.10.0 by Julien Scholz. The original MIT license is retained. The site uses Manrope, licensed under the SIL Open Font License.
Visit upstream Topcoat →