Topcoat: build a Rust web app without a separate JavaScript project
Topcoat brings server-rendered pages, selective Rust-to-JavaScript reactivity and server-updated components into one Rust web app. Version 0.9 is promising, but still experimental.
By George the bot
Edited and approved by Faysal Aziz
Published

If your back end is already Rust, building the ordinary browser bit can feel like opening a second workshop. Now you have a JavaScript project, a client build, a routing decision and another set of dependencies to tend. Topcoat, a new framework from the Tokio team, is trying to make the everyday database-backed web app feel like one Rust project again.
The public release is version 0.9, so this is an experiment worth learning from, not a recommendation to move a production system tomorrow. The interesting question is whether its mix of server rendering and small browser updates gives you enough interactivity without making you build a separate front end.
How the pieces fit
Topcoat starts with server-rendered HTML. Its view! macro mixes markup with Rust control flow, while routes follow the project's module tree. There is an asset pipeline with content-hashed URLs and a Tailwind integration that does not require Node.js. For data access, the project is working toward tighter integration with Toasty, Tokio's asynchronous ORM.
The clever part is the $(...) expression. You write a selected, type-checked Rust expression; Topcoat evaluates it for the first server render and translates it into JavaScript for quick updates in the browser. That is not a WebAssembly bundle, and it is not a promise that all Rust code becomes browser code. It is a narrower way to keep simple reactive behaviour near the view that uses it.
When a change needs server work, a #[shard] component can be rendered again on the server and its HTML swapped into the page. Think of a searchable order list or a dashboard panel that updates without reloading the whole screen. You still have to design the data flow and test what happens when the network is slow; the framework does not make those decisions disappear.
A sensible first build
Try a small internal tool: customers, orders and a filtered list. Make one route that renders the list, one form that adds a record, a browser-side filter using a suitable $(...) expression, and one server-backed shard that refreshes a summary. That exercise will show where Topcoat saves you plumbing and where a request still has to cross the network.
Pay attention to the less glamorous skills, too: how module-based routes are organised, how database migrations are handled, how the asset pipeline behaves in deployment and how much JavaScript the resulting page actually ships. Topcoat UI components are copied into your project, so inspect and adapt them as your own code rather than assuming a remote package will manage their design forever.
Keep the 0.9 label in view
Authentication, background jobs, static export and tighter Toasty integration are still on the roadmap. Releases in the 0.x line may require changes, even though the team says it will provide release notes and migration guidance. That makes a prototype or a modest internal app a better starting point than a system that depends on those missing pieces.
Topcoat will not replace every JavaScript front end, and it is not yet a Rust Django. But for a developer who already knows Rust, it offers a useful thing to learn: how far server-rendered pages, focused client reactivity and selective server updates can take a real business app before a separate front-end project earns its keep.