TanStack Start SSR Implementation in the OpenCut Web Application
OpenCut leverages TanStack Start to enable zero-configuration server-side rendering through a Vite plugin that generates a Cloudflare Workers-compatible server entry, automatically wires the router tree, and streams HTML from the edge while preserving full client-side hydration.
The OpenCut web application utilizes TanStack Start as its primary framework for implementing SSR, extending TanStack Router with built-in server rendering capabilities. This architecture delivers fully rendered initial HTML from Cloudflare's edge network while maintaining a seamless single-page application experience after client-side hydration. Examining the TanStack Start SSR implementation in OpenCut reveals a modern approach to React server rendering that eliminates manual configuration through intelligent code generation.
Vite Configuration and Plugin Architecture
The foundation of OpenCut's SSR pipeline begins with Vite configuration that registers the TanStack Start plugin. In apps/web/vite.config.ts, the tanstackStart plugin from @tanstack/react-start/plugin/vite automatically injects the server entry point and manages route tree generation.
import { devtools } from '@tanstack/devtools-vite'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
export default defineConfig({
plugins: [
devtools(),
tanstackStart(), // Registers SSR entry and route generation
],
})
The tanstackStart() function configures Vite to generate a custom serverEntry that renders the React tree on the edge server. This plugin eliminates manual webpack or server configuration by automatically creating the bridge between TanStack Router and the Cloudflare Workers runtime.
Router Creation and Type Registration
OpenCut defines its routing logic in apps/web/src/router.tsx, exporting a getRouter function that instantiates the TanStack Router with SSR-specific optimizations.
import { createRouter as createTanStackRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'
export function getRouter() {
return createTanStackRouter({
routeTree,
scrollRestoration: true,
defaultPreload: 'intent',
defaultPreloadStaleTime: 0,
})
}
The router configuration uses defaultPreload: 'intent' to enable built-in data pre-fetching for upcoming routes before rendering occurs. The scrollRestoration parameter ensures consistent scroll behavior between server and client environments, while defaultPreloadStaleTime: 0 guarantees fresh data on every navigation.
Generated Route Tree Integration
The apps/web/src/routeTree.gen.ts file auto-generates TypeScript interfaces that register the router type for SSR consumption. This generated code creates a critical type bridge:
interface Register {
ssr: true;
router: Awaited<ReturnType<typeof getRouter>>;
}
This registration enables the TanStack Start server entry to resolve the router type at runtime, ensuring type safety across the server-client boundary without manual type declarations.
Edge Server Entry Point
OpenCut deploys to Cloudflare Workers using the TanStack Start server entry module configured in apps/web/wrangler.jsonc. The configuration specifies:
{
"main": "@tanstack/react-start/server-entry"
}
This entry point imports the generated route tree, which subsequently imports getRouter from apps/web/src/router.tsx. When a request hits the Cloudflare Worker, the server entry performs the following operations:
- Resolves the matching route using the router tree
- Executes loader functions for data pre-fetching based on
defaultPreloadsettings - Renders the React component tree to HTML using
ReactDOMServer.renderToPipeableStream - Streams the HTML response back to the browser
The architecture leverages Cloudflare's edge network to run SSR code geographically close to users, minimizing latency for the initial document request.
Root Document Shell
The apps/web/src/routes/__root.tsx file defines the HTML skeleton that wraps all routes during SSR. This component provides the top-level layout that the server renders and streams to clients.
export const Route = createRootRoute({
head: () => ({
meta: [{ charSet: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }],
title: 'OpenCut rewrite — beta.opencut.app',
}),
shellComponent: RootDocument,
})
function RootDocument({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<HeadContent />
</head>
<body>
{children}
<Scripts />
</body>
</html>
)
}
The HeadContent component injects meta tags and CSS bundles, while Scripts handles the client-side JavaScript hydration. This structure ensures the server sends a complete HTML document with proper <head> elements before the client entry (@tanstack/react-start/client-entry) hydrates the router state.
Deployment and Build Process
The deployment pipeline utilizes standard npm scripts defined in apps/web/package.json:
{
"scripts": {
"deploy": "bun run build && wrangler deploy"
}
}
Running npm run deploy executes the Vite build process, which triggers the tanstackStart plugin to generate the SSR entry and route tree typings. The Wrangler CLI then deploys the Cloudflare Worker containing the server entry module, making the TanStack Start SSR implementation live on the edge network.
Summary
- Zero-config SSR: The
tanstackStartVite plugin automatically generates server entries and route typings without manual webpack configuration. - Edge-optimized deployment: Cloudflare Workers execute the SSR logic close to end users, reducing time-to-first-byte latency.
- Type-safe routing: The generated
routeTree.gen.tsregisters router types for both server and client environments. - Built-in pre-fetching:
defaultPreload: 'intent'inrouter.tsxfetches route data before rendering begins. - Streaming HTML: The server uses
ReactDOMServer.renderToPipeableStreamto send progressive HTML chunks to the browser.
Frequently Asked Questions
How does routeTree.gen.ts enable SSR in TanStack Start?
The routeTree.gen.ts file auto-generates a TypeScript Register interface that declares ssr: true and types the router using Awaited<ReturnType<typeof getRouter>>. This allows the @tanstack/react-start/server-entry module to import type-safe router instances at runtime, ensuring the server renders the correct component tree while maintaining full TypeScript intellisense across the server-client boundary.
What triggers data pre-fetching during the SSR process?
The defaultPreload: 'intent' configuration in apps/web/src/router.tsx instructs TanStack Router to execute route loader functions as soon as the user indicates navigation intent. During SSR, this means the server entry walks the matched route tree, awaits all loader promises, and embeds the dehydrated data into the HTML stream before React renders the component tree, eliminating client-side loading states for initial data.
Why does OpenCut use Cloudflare Workers specifically for TanStack Start?
OpenCut targets Cloudflare Workers because TanStack Start's server entry (@tanstack/react-start/server-entry) conforms to the WinterCG standard, making it compatible with edge runtimes. The wrangler.jsonc configuration points directly to this entry module, allowing the Worker to execute the SSR logic on Cloudflare's global edge network, which reduces latency compared to traditional origin-server rendering while maintaining the full TanStack Router feature set.
What is the relationship between the server entry and client entry in this architecture?
The server entry (@tanstack/react-start/server-entry) handles the initial request by rendering the React tree to HTML on the Cloudflare Worker, while the client entry (@tanstack/react-start/client-entry) hydrates that same tree in the browser. The Scripts component injected in apps/web/src/routes/__root.tsx loads the client entry, which reuses the router state dehydrated by the server, creating a seamless transition from server-rendered HTML to interactive SPA without full page reloads.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →