Topcoat
The full full-stack framework for Rust
Topcoat is a modular, batteries-included Rust framework for building fullstack apps. It prioritizes simplicity and productivity. See the Getting started guide to set up a new project.
Early-stage and experimental. Expect breaking changes.
use topcoat :: { Result , router :: { Router , RouterBuilderDiscoverExt , page } , view :: { component , view } , } ; # [ tokio :: main ] async fn main ( ) { topcoat :: start ( Router :: builder ( ) . discover ( ) . build ( ) ) . await . unwrap ( ) ; } # [ page ( "/" ) ] async fn home ( ) -> Result { view ! { <! DOCTYPE html> <html> <body> hello ( name : "World" ) </body> </html> } } # [ component ] async fn hello ( name : & str ) -> Result { view ! { <h1> "Hello, " ( name ) "!" </h1> } }
What makes Topcoat different
Client reactivity without the boilerplate
Topcoat renders all markup on the server: components can be async and query the database directly, eliminating all the traditional boilerplate needed for a separate API layer. Interactivity does not have to cost a round-trip, though. A $(...) expression is ordinary type-checked Rust that Topcoat evaluates on the server for the initial render and also translates to JavaScript, so it re-runs instantly in the browser. No wasm bundle, no client build step:
view ! { signal open = false ; // Runs entirely in the browser; no server round-trip. <button @click=$ ( |_e| open . set ( !open . get ( ) ) ) > "What is Topcoat?" </button> <p : hidden=$ ( !open . get ( ) ) > "A fullstack Rust framework." </p> }
When an update does need the server, like fresh search results, mark the component as a #[shard] . Topcoat re-renders it on the server whenever one of its $(...) arguments changes and swaps the new HTML in place:
... continue reading