@roostjs/start
Why Roost integrates with TanStack Start, how the context bridge connects server and client, and what SSR looks like on Workers.
Why TanStack Start Over Next.js or Remix
The React full-stack framework space has several contenders. Next.js is the most widely deployed. Remix prioritizes web fundamentals. Both are designed primarily for Node.js and have varying levels of support for edge runtimes. TanStack Start is different in a relevant way: it is runtime-agnostic at its core and designed to run on Cloudflare Workers as a first-class deployment target, not as an afterthought.
More concretely, TanStack Start's routing model is file-based but builds on TanStack Router, which has some of the strongest TypeScript integration of any React router. Route params are typed. Loader data is typed. Search params are validated and typed. For applications that take TypeScript seriously, this type safety propagates from the URL into the component tree without manual casting. That alignment with Roost's TypeScript-first design made TanStack Start the right foundation.
The Context Bridge
Roost runs server-side: it boots, registers providers, and makes services available through the container. TanStack Start runs server-side rendering and client-side hydration. The challenge is connecting these two systems so that server functions and route loaders can access Roost's container — the authenticated user, resolved organization, database connection — without the container being globally mutable state.
The @roostjs/start package solves this with a context bridge. The Roost
Application is bootstrapped once and cached. For each request, a scoped
container is created and attached to TanStack Start's server context. Server functions
defined with roostFn capture this context and can resolve services from it.
The bridge is the mechanism that makes the scoped container travel through TanStack Start's
data-loading layer without being a global singleton.
SSR on Workers vs. Node.js
Server-side rendering in Node.js typically means a long-running process that handles
React's renderToString or streaming equivalents. On Workers, there is no
persistent server process — each request is handled fresh (possibly by a warm isolate,
but without server-process-level assumptions). This means SSR happens per-request,
which is actually the semantically correct behavior for dynamic applications: every
visitor gets a server render reflecting the current server state, not a stale render
from a warm cache.
The Workers runtime includes V8's streaming APIs, so TanStack Start's streaming SSR works natively. The main practical difference from Node.js is that Workers do not have Node.js built-ins, so any SSR code or its dependencies must be compatible with the Web Platform APIs. TanStack Start is designed for this; Roost's integration does not paper over any incompatibilities.