Carl Lerche and Julien Scholz, who support Rust's async runtime Tokio, have announced a full-stack web framework called "Topcoat." While rendering all HTML on the server, it converts some type-checked Rust expressions into JavaScript to update state in the browser without loading WebAssembly (WASM). This is less an attempt to recreate SPAs in Rust than a design that brings Rust's types and toolchain into server-centric web development. That said, the official documentation itself explicitly states the project is still experimental, and there are no measurement results yet that would let anyone conclude it is "better than Next.js."

AD

From 0.1 to 0.5 in 11 Days: An API That Keeps Changing Right After Launch

Topcoat 0.1.0 was published to crates.io on July 16, 2026. The announcement on the official Tokio blog came on the 22nd, followed by 0.5.0 on the 27th. Only 11 days separate 0.1.0 from 0.5.0, and 41 commits were made between 0.4.0 and 0.5.0. Support for WebSockets and Server-Sent Events (SSE) was added, along with prototype Datastar integration and email sending. Breaking changes were also made to the layout and router.

The volume of 41 changes is not proof of stability. The README explicitly states it is "early-stage and experimental" and asks users to expect breaking changes. At this stage, Topcoat is not a finished product promising long-term operational reliability, but a release meant for exploring the design direction and feasibility of implementation.

The motivation behind the development also isn't focused solely on page-rendering speed. Lerche explains that thanks to AI assistance, the burden of learning a new language and the resulting productivity gap have both shrunk. His view is that organizations that already have Rust libraries, build infrastructure, and internal processes stand to benefit from using the same language for high-level web applications as well. Rather than making the general argument that everyone should migrate to Rust, Topcoat is trying to answer a narrower question: can organizations that have already adopted Rust avoid adding more languages and tools?

Reactivity Achieved by Compiling Rust Expressions Twice

The $(...) construct at the heart of Topcoat is not a mechanism for bringing arbitrary Rust code into the browser. The macro compiles a restricted set of expressions twice, generating both the Rust code that produces the initial HTML and the equivalent JavaScript that re-executes in the browser. The initial value is evaluated on the server, and when a signal representing state changes, the JavaScript-side expression updates text or attributes. For things like opening/closing a button or syncing with an input field, no round trip to the server occurs.

For updates that touch the database, two paths are provided. #[procedure] lets the browser call an async server function over HTTP. #[shard] sends a state change to the server, re-renders the component, and swaps in the returned HTML fragment. Rather than hydrating the entire screen, local processing is delegated to a small runtime, while the server explicitly returns only the processing that is actually needed.

So "no WASM required" does not mean "no JavaScript required." As of July 29, 2026, the browser runtime included in the repository was 18,065 bytes uncompressed, and on top of that come each page's reactive expressions and metadata. There is also an escape hatch for writing raw JavaScript for anything the syntax can't express. What Topcoat reduces is the burden of maintaining a separate frontend stack and a WASM build pipeline—not the browser's execution environment itself.

The constraints are clear. The official reference describes the types and methods the expressions can handle as a "small vocabulary," and describes the current runtime as "very experimental and quite limited." Type checking can reduce Rust syntax errors, but it does not expand the range of Rust that can be converted into JavaScript. Applications that require complex client-side processing may hit this boundary early on.

AD

The Scope of "Batteries Included" Is Concentrated on the Surface of the Web

The features in 0.5.0 fall into three categories: those enabled by default, those added via full, and those planned for future implementation.

Stage Main Features
Default Routing, SSR views, assets and compression, cookies and sessions, fonts and icons, client-side reactivity
Added via full Tailwind CSS and editable UI components, HTMX and Alpine AJAX, Datastar, email and SMTP, multipart, SSE and WebSocket, Tower integration
Roadmap Authentication and input validation, background jobs, localization, static export, streaming SSR, client-side navigation, image optimization, deployment procedures

The range this covers—bringing everything from pages to communication channels into a single Rust workspace—is already broad. However, enabling full does not mean all operational features are complete. The existence of session management is a different thing from having fully realized authentication features, from login through to authorization design.

The data layer is similar. The official announcement recommends adding the async ORM Toasty if you need a database. An ORM is not included in Topcoat's full feature, and tight Toasty integration for safely updating records from forms remains a task for the future. Reading "batteries-included" accurately, at this stage, means understanding it as covering the web's display and communication layers broadly.

The way UI components are distributed reflects the framework's philosophy well. Tailwind-based components are not hidden deep inside a dependency package; instead, topcoat ui copies them directly into the app's source. Developers can directly modify the generated markup and behavior. Assets, too, are collected from asset! declarations and served via content-hashed URLs. Rather than wrapping everything in abstraction, this is a design that lets you keep the necessary code close at hand and edit it directly.

Where It Diverges from Leptos, Dioxus, and Axum

Leptos and Dioxus also let you write both frontend and backend in Rust. Leptos offers fine-grained reactive updates and server functions. Dioxus Fullstack integrates with Axum, handling post-SSR hydration along with WebSocket and SSE. It also supports static generation and deployment targeting WASM. If you want to run substantial Rust programs in the browser as well, both of these have a broader scope.

Topcoat reduces a different kind of burden. It pushes HTML and data fetching toward server-side components, while the browser runs JavaScript converted from a restricted set of Rust expressions. This fits well with admin panels, internal tools, and content sites—applications where the server returns finished HTML, but you still want immediate responsiveness for things like search, expand/collapse, and forms. For use cases involving large client-side state machines or offline processing, the constraints will stand out sooner.

Its relationship to Axum is more of a layering than a rivalry. Axum is a thin library focused on HTTP routing and request handling, combined with Tower middleware. On top of that, Topcoat provides defaults for the template, asset, session, and browser-update flows that developers previously had to choose every time. The official announcement, too, envisions using Axum for low-level APIs and combining both within the same project.

AD

Three Conditions to Measure Before Comparing to Next.js

Topcoat's repository includes a benchmark setup that renders the same product catalog using Next.js 15 App Router, Leptos 0.8, and a combination of Axum 0.8 with Maud. What's being compared is server-side processing up to returning complete HTML over HTTP; it does not measure browser interactivity time, or the fetching of CSS, JavaScript, and images. The location where measurement results are stored is excluded from Git tracking, and no official score table has been published. At least for now, there is no primary data to support concluding that it is "faster than Next.js" or "better."

In real-world deployment, there are two boundaries worth confirming before performance. First, the current browser runtime turns handlers embedded in HTML attributes into functions using new Function. Under the Content Security Policy (CSP) specification, generating functions from strings is blocked by policies that don't allow unsafe-eval. Services that require strict CSP will need to verify whether they can operate without relaxing their policy, until Topcoat's implementation changes or a safe alternative is put in place. This is not a certified vulnerability, but rather a question of compatibility between the current implementation and deployment requirements.

Second, #[procedure] and #[shard] become HTTP endpoints on the server. The official reference explicitly states that arguments sent from the browser should be treated as values that can be forged, and should not be trusted. Even though components can call server-side permission checks, that does not automatically guarantee input validation and authorization.

Topcoat has demonstrated that Rust and SSR can be combined with localized reactivity. What will change adoption decisions is not the number of features in 0.5.0. First, the API needs to stabilize, and authentication and deployment procedures need to be filled in. Only once it can operate under strict CSP, and once development time and delivery performance can be compared under equivalent measurement conditions, will it stand on the same footing as existing full-stack platforms.