Building a web app in Rust has long meant choosing between two costs. Either you split the front and back end and hand-write a pile of interfaces and data transfer objects, or you pull in wasm and a bundler and carry a whole client toolchain for one button. tokio-rs/topcoat tries to skip that choice. It renders every component on the server, where an async function can query the database directly, while keeping client-side reactivity, all without a wasm bundle or a client build step.
What Is topcoat
topcoat comes from tokio-rs, the team behind Tokio and Axum. It is a batteries-included full-stack web framework that puts simplicity and productivity first. In one line, it renders everything on the server but keeps interactions responsive. Components can be async functions that query a database inline, with markup generated on the server, so the API layer that split front ends and back ends require simply disappears. The repository was created in April 2026 and still saw commits in November 2026. It has about 6,898 stars and 304 forks under the MIT license. The project is explicitly labeled early and experimental, with breaking changes expected, which suits early adopters more than production use. It shares the native-speed outlook of tools like What Is Zed and How to Use It.
Features
- No API layer. Components await database queries directly and render markup on the server, so there is no interface or transfer object to maintain.
- Type-safe reactivity. A
$(...)expression is evaluated on the server for the first render and translated into JavaScript to rerun in the browser, all in ordinary Rust. - Partial rerender. Mark a component
#[shard]and its HTML is rebuilt on the server whenever its$(...)inputs change. - Macro-driven views.
view!mixes HTML, Rust expressions, control flow, and component calls, with#[component]and#[page]declaring each piece. - State and events.
signal(cx, || ...)declares state, and bindings like@clickand@inputupdate it directly. - Supporting primitives.
attributes!,class!,suspense,error_boundary,live!, andemit!cover attribute merging, conditional styles, loading fallbacks, error boundaries, and local live swaps. - No client build. There is no wasm bundle and no bundler. Deployment runs the server only.
It takes the reactive-without-boilerplate idea further than most Rust frameworks, keeping the whole app in one language and one toolchain. Type checking therefore spans the database query, the component, and the event handler without a boundary in between.
How to Use
- Run
topcoat newto scaffold a project. The generator sets up routes and page structure. - Write markup with
view!and pull reusable pieces into async functions with#[component]. - When a page needs data, await the query inside the component and skip the interface layer.
- Declare state with
signal(cx, || ...), read it in markup through$(...), and update it with bindings like@click. - Mark any block that needs fresh server data as
#[shard]. Its HTML swaps in automatically when inputs change. - Build links and forms with
href!, then runtopcoat fmtto tidy macro bodies. For the Rust toolchain behind it, see What Is Ruff and How to Use It.
One caution. It is still experimental and its interfaces may shift, so pin the version on a team project.
Supported Platforms
| Item | Detail |
|---|---|
| Language | Rust |
| Foundation | Axum, the tokio-rs async stack |
| Routing | Pages, layouts, API routes, plus module_router!() discovery |
| Client | No wasm, no client build |
| License | MIT |
| Stage | Early experiment, breaking changes possible |
There is no special editor or operating system requirement. A working Rust toolchain is enough, and deployment ships the server binary with no client artifact. Because markup is rendered on the server, a page still loads without JavaScript until a $(...) expression or an @click binding needs the browser. That keeps operations simple, though the experimental stage calls for pinned versions and tracking upstream changes.
Pricing
topcoat is open source under the MIT license. Use, modification, and redistribution are free, including in commercial projects. There is no hosted service, support contract, subscription, or paid tier. The real cost is maintenance. While it remains experimental, a team should budget for pinning versions and tracking upstream changes, which matters more here than any licensing question. Try it on a small slice of a real project before committing, the sensible path while interfaces are still settling.
Use Cases
- Small full-stack teams. One person owns both sides without maintaining two projects and an interface contract.
- Data-heavy pages. Components query the database inline, cutting a layer of serialization and type mapping.
- Light interaction. Forms, filters, and partial refreshes use shards instead of a front-end framework.
- Rust shops. Teams already on Axum or Tokio keep end-to-end type safety.
- Prototypes. Turn an idea into a running web app without build configuration.
- Teaching. Show server rendering and reactivity in one language instead of switching to JavaScript.
Large multi-platform products that lean on a mature plugin ecosystem still need to weigh the experimental-stage risk before adopting it. For a greenfield app with modest interactivity, the trade is unusually clean, since there is no client pipeline to maintain at all.
How It Works
topcoat is built and maintained by tokio-rs, borrowing the credibility of Tokio and Axum, and developed in the open through issues and pull requests. Its bet is deliberate. Rather than fight Leptos, Dioxus, and Loco on client-side features, it concentrates on full server rendering plus type-safe reactivity, with no wasm and no client build as the headline. That suits teams who think in terms of the server. Because the project is in an experimental phase, documentation and features are still filling in, and adopters accept shifting interfaces. In return, early feedback carries more weight in shaping direction. The server-first bet also means a small team needs no separate front-end build pipeline, no bundler configuration, and no wasm toolchain to keep current as the app grows.
Conclusion
If you are tired of wiring a whole front-end build for one button but reluctant to give up Rust's end-to-end type safety, topcoat offers a rare middle path. It compiles interactions into code the browser can run, keeps data on the server, and removes the hand-written interface in between. The experimental label is real, so try it on a small slice of production first and pin the version. If one language end to end appeals to you, few frameworks make the case as neatly.