Announcing Topcoat: a framework for building full-stack reactive web apps with Rust
7 points by jado
7 points by jado
As someone who has tried Leptos and felt somewhat stunted working with wasm-bindgen, I am initially optimistic for this framework. Good luck to Carl and all!
previously: https://lobste.rs/s/zmg7ot/topcoat_batteries_included_framework (probably should be merged?)
Wow, that view macro. A templating language defined in terms of Rust tokens. I hope the error messages are good.
First, thank you for elaborating on this. Especially "Reactivity without WebAssembly", which answered my biggest question previously.
Three years ago, if I told you that Rust would be a great language to build web apps with, you probably would call me crazy, and rightfully so. After all, web apps aren't traditionally performance-sensitive applications. So, the right tool for the job would be one that lets you ship fast. Performance is a nice-to-have.
Ehh... (tilty "so-so" hand gesture)
While I can certainly see enterprises throwing more resources at a project written in a language like PHP, Ruby, etc., I'm very aware of my budget as a hobbyist webmaster, and Go was developed because Google was already using C++ where others would use PHP/Python/Ruby/etc. for performance reasons.
More importantly, for me, migrating from Python to Rust has never been about performance, but about correctness ("I'm tired of how many unit tests I had to write for my Django apps to catch dumb mistakes a proper type system would have caught at compile time"), Go-like simplicity of deployment, and static linking for independence from "OK, I upgraded my distro. What were the steps to un-break my virtualenvs again?"
Strict-mode MyPy plus PyQt and QWidget is better at catching mistakes than QML in Qt apps, and Rust is better than strict-mode MyPy at catching mistakes in web apps.
I started with Toasty, an ORM for Rust, because it is probably the hardest component. Toasty has been ready to use since April of 2026.
I always welcome more options, but I'm having trouble determining whether Toasty does any better than SeaORM on the two things that keep me in Python and on Django ORM or SQLAlchemy for non-trivial projects:
ALTER TABLE.Reactivity without WebAssembly
I do find this compelling.
Throw in some kind of compile-time switch to disallow any constructs which can't support a "Render as server-side code, but support hydration to speed things up when the user has JS" and I'd be very interested.
fontsource_font!(ROBOTO);
iconify::include!("feather");
I generally write my modern-day creations to use Content-Security-Policy to forbid non-'self' requests... both for user privacy and because it's an additional point of failure even without things like uMatrix and NoScript whitelisting on a domain-by-domain basis. Browsers have been including the top-level resource's origin in their cache keys for years now to limit the amount of information companies like Google can derive from their CDN logs, so it's going to be downloaded again for my site either way.
Do I have to fall back to manually downloading these sorts of things and using a bunch of asset!("./roboto.ttf"); asset!("./roboto.woff");, fallback cascades or is there a switch to support my use-case?
...ideally one where I can run a command to cache the files so I can commit them to the repo to be compatible with how things like Gentoo Portage and flatpak-builder break the build process into two phases: "Download from a declarative manifest with execution forbidden." and "Compile with the network sandboxed away."
Locality of behavior as the guiding principle
I'll need to think about how this interacts with my security model. For example, at the moment, I'm finishing work on a more expressive wrapper for cap_std::fs::Dir for one of my web projects, where the idea is that explicitly passing arguments in is part of the security boundary and each request starts with a let mut req_root = www_root.constrain(&parent_dir_for_url_path) and, once any necessary metadata sidecar files have been loaded (eg. a folder description at something like .description.md), stuff like req_root.restrict_in_place( ShareRootOpts { allow_hidden: false, ..Default::default() }) can enable the wrapper-added restrictions on req_root.open(...) and req_root.read_dir_async(...).
"letting components do their own data fetching" feels like it would add some urgency to my idea to use server-side webassembly to move things like templating, thumbnailing, etc. into WebAssembly modules for nanoprocess sandboxing of transitive dependencies.
EDIT: To anyone wondering about my deleted post, it was a duplicate of this while I was trying to correct a "but but" duplication and did this again. (TL;DR: Accidentally edited and re-posted an automatically refilled-by-the-browser post form instead of scrolling down to the edit form, editing there, and clicking Update.)