Loading...
Loading...
Ossido is a full-stack framework that puts a React frontend and a Rust (axum) backend in one project, behind one dev server. You write your UI in React and your data-loading and routing in Rust, and Ossido wires the two together - server-rendering your React with data produced in Rust, then hydrating it in the browser.
At a high level, an Ossido app is:
You don't run two projects or stitch a separate API to a separate SPA. Routes,
data handlers, and pages live side by side under src/routes, and a single
ossido dev process serves all of it.
It helps to keep three moving parts in mind:
Rust never "runs React" directly. It hands your data to the SSR bundle, which renders React inside V8 and returns HTML that Rust streams to the client.
Server-rendering React means running JavaScript from inside the Rust process, so the choice of embedded engine matters. We evaluated three candidates - JavaScriptCore (JSC), V8, and SpiderMonkey - against the things that actually matter for per-request SSR:
In our testing, V8 consistently came out with the best balance of the three. JSC and SpiderMonkey each had bright spots on individual axes, but V8 was the most dependable all-rounder - and a render pool serving many requests needs a consistent all-rounder, not a specialist. That's why the render pool is built on a pool of V8 isolates.
A single page request flows like this:
The important part is the ordering: data first, then render. Your Rust handler is the source of truth for what the page needs; React only ever sees the result as props.
The lifecycle above is the first load. After that, navigating between routes
with the router's Link keeps you in a single-page app - it does not request
a whole new HTML page. Instead the router fetches just the destination route's
props and renders the React page on the client:
/__ossido/data/<path>), which re-runs the route's Rust #[handler] and
returns the props as JSON - no HTML re-render..json file instead.Either way the contract is identical to the first load: the Rust handler is still the source of the data and your page still receives the same typed props - the only difference is that the props arrive as JSON and React renders them in the browser rather than on the server.
The cleanest way to reason about an Ossido app is to ask, for anything you build, which side of the boundary does this belong to?
Data crosses the boundary in exactly one direction at render time: a handler's
return value becomes the page component's props. A Rust struct marked with
the #[Props] macro is serialized on the server and arrives in your React
component fully typed - no manual fetch, no client round-trip for the initial
data.
Ossido has two output modes, chosen in ossido.config.ts (and overridable at
build time):
static - pages are generated to HTML at build time (SSG). Best for
content that doesn't change per request; deploy the output to any static host.server - pages are rendered per request by the standalone server binary
(SSR). Use this when a page depends on the request (auth, dynamic data,
personalization).Everything above - handlers, props, the Rust/React boundary - works the same in both modes. The difference is when the render happens: once at build time, or on every request.
Ossido and Next.js solve overlapping problems but make opposite bets, so the right choice depends on your workload. Here's an honest look at where each shines and where each falls short.
Strengths
#[Type] macro), so your data layer gets Rust's performance, safety, and
ecosystem.Shortcomings
Strengths
Shortcomings
The RSC difference is fundamental. Next.js supports React Server Components;
Ossido does not, and likely never will. Ossido's model is deliberately different -
data comes from Rust #[handler]s and crosses into React as props, rather than
from server components rendered inside the JavaScript runtime. If your
architecture depends on RSC, Next.js is the natural fit.
In short: choose Ossido to saturate multiple cores and keep data-loading in Rust; choose Next.js for single-core simplicity, the Node ecosystem, or an RSC-centric architecture.
Next: Installation & project setup · The CLI