# TanStack Start SSR Implementation in the OpenCut Web Application

> Implement TanStack Start SSR in OpenCut for zero-config server-side rendering. Stream HTML from the edge with Vite plugin for seamless client-side hydration.

- Repository: [OpenCut.app/OpenCut](https://github.com/OpenCut-app/OpenCut)
- Tags: how-to-guide
- Published: 2026-06-23

---

**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`](https://github.com/OpenCut-app/OpenCut/blob/main/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.

```typescript
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`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/src/router.tsx), exporting a `getRouter` function that instantiates the TanStack Router with SSR-specific optimizations.

```typescript
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`](https://github.com/OpenCut-app/OpenCut/blob/main/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:

```typescript
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:

```json
{
  "main": "@tanstack/react-start/server-entry"
}

```

This entry point imports the generated route tree, which subsequently imports `getRouter` from [`apps/web/src/router.tsx`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/src/router.tsx). When a request hits the Cloudflare Worker, the server entry performs the following operations:

1. Resolves the matching route using the router tree
2. Executes loader functions for data pre-fetching based on `defaultPreload` settings
3. Renders the React component tree to HTML using `ReactDOMServer.renderToPipeableStream`
4. 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`](https://github.com/OpenCut-app/OpenCut/blob/main/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.

```tsx
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`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/package.json):

```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 `tanstackStart` Vite 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.ts`](https://github.com/OpenCut-app/OpenCut/blob/main/routeTree.gen.ts) registers router types for both server and client environments.
- **Built-in pre-fetching**: `defaultPreload: 'intent'` in [`router.tsx`](https://github.com/OpenCut-app/OpenCut/blob/main/router.tsx) fetches route data before rendering begins.
- **Streaming HTML**: The server uses `ReactDOMServer.renderToPipeableStream` to send progressive HTML chunks to the browser.

## Frequently Asked Questions

### How does [`routeTree.gen.ts`](https://github.com/OpenCut-app/OpenCut/blob/main/routeTree.gen.ts) enable SSR in TanStack Start?

The [`routeTree.gen.ts`](https://github.com/OpenCut-app/OpenCut/blob/main/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`](https://github.com/OpenCut-app/OpenCut/blob/main/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`](https://github.com/OpenCut-app/OpenCut/blob/main/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.