---
description: Deploy a TanStack Start application to Cloudflare Workers.
title: TanStack Start
image: https://developers.cloudflare.com/og-docs.png
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/workers/llms.txt  
> Use this file to discover all available pages before exploring further.

# TanStack Start

Last updated Aug 24, 2026|Copy as Markdown|[View as Markdown](https://e8aee267.previews.developers.cloudflare.com/workers/framework-guides/web-apps/tanstack-start/index.md)|[Agent setup](https://e8aee267.previews.developers.cloudflare.com/agent-setup/)

[TanStack Start ↗](https://tanstack.com/start) is a full-stack framework for building web applications with server-side rendering, streaming, server functions, and bundling.

Already have a TanStack Start project?

Run `wrangler deploy` in a project without a Wrangler configuration file and Wrangler will automatically detect TanStack Start, generate the necessary configuration, and deploy your project.

npmyarnpnpm

```
npx wrangler deploy
```

```
yarn wrangler deploy
```

```
pnpm wrangler deploy
```

Learn more about [automatic project configuration](https://e8aee267.previews.developers.cloudflare.com/workers/framework-guides/automatic-configuration/).

TanStack StartDetected

Generated configuration

wrangler.jsonc

main:.output/server/index.mjs

wrangler.jsonc

assets:directory: .output/public

wrangler.jsonc

compatibility\_flags:nodejs\_compat

wrangler.jsonc

observability:enabled: true

WorkersDeployed

Wrangler handles configuration automatically

## Create a new application

Create a TanStack Start application pre-configured for Cloudflare Workers:

npmyarnpnpm

```
npm create cloudflare@latest -- my-tanstack-start-app --framework=tanstack-start
```

```
yarn create cloudflare my-tanstack-start-app --framework=tanstack-start
```

```
pnpm create cloudflare@latest my-tanstack-start-app --framework=tanstack-start
```

Start a local development server to preview your project during development:

npmyarnpnpm

```
npm run dev
```

```
yarn run dev
```

```
pnpm run dev
```

## Configure an existing application

If you have an existing TanStack Start application, configure it to run on Cloudflare Workers:

1. Install `@cloudflare/vite-plugin` and `wrangler`:  
npmyarnpnpmbun  
```  
npm i @cloudflare/vite-plugin wrangler -- -D  
```  
```  
yarn add @cloudflare/vite-plugin wrangler -D  
```  
```  
pnpm add @cloudflare/vite-plugin wrangler -D  
```  
```  
bun add @cloudflare/vite-plugin wrangler -D  
```
2. Add the Cloudflare plugin to your Vite configuration:  
```js  
import { defineConfig } from "vite";  
import { tanstackStart } from "@tanstack/react-start/plugin/vite";  
import { cloudflare } from "@cloudflare/vite-plugin";  
import react from "@vitejs/plugin-react";  
export default defineConfig({  
	plugins: [  
		cloudflare({ viteEnvironment: { name: "ssr" } }),  
		tanstackStart(),  
		react(),  
	],  
});  
```  
```ts  
import { defineConfig } from "vite";  
import { tanstackStart } from "@tanstack/react-start/plugin/vite";  
import { cloudflare } from "@cloudflare/vite-plugin";  
import react from "@vitejs/plugin-react";  
export default defineConfig({  
	plugins: [  
		cloudflare({ viteEnvironment: { name: "ssr" } }),  
		tanstackStart(),  
		react(),  
	],  
});  
```
3. Add a `wrangler.jsonc` configuration file:  
```jsonc  
{  
	"$schema": "node_modules/wrangler/config-schema.json",  
	"name": "<YOUR_PROJECT_NAME>",  
	// Set this to today's date  
	"compatibility_date": "2026-08-24",  
	"compatibility_flags": ["nodejs_compat"],  
	"main": "@tanstack/react-start/server-entry",  
	"observability": {  
		"enabled": true,  
	},  
}  
```  
```toml  
"$schema" = "node_modules/wrangler/config-schema.json"  
name = "<YOUR_PROJECT_NAME>"  
# Set this to today's date  
compatibility_date = "2026-08-24"  
compatibility_flags = [ "nodejs_compat" ]  
main = "@tanstack/react-start/server-entry"  
[observability]  
enabled = true  
```
4. Update the `scripts` section in `package.json`:  
```json  
{  
	"scripts": {  
		"dev": "vite dev",  
		"build": "vite build",  
		"preview": "vite preview",  
		"deploy": "npm run build && wrangler deploy",  
		"cf-typegen": "wrangler types"  
	}  
}  
```

## Deploy

Deploy to a `*.workers.dev` subdomain or a [custom domain](https://e8aee267.previews.developers.cloudflare.com/workers/configuration/routing/custom-domains/) from your machine or any CI/CD system, including [Workers Builds](https://e8aee267.previews.developers.cloudflare.com/workers/ci-cd/builds/).

npmyarnpnpm

```
npm run deploy
```

```
yarn run deploy
```

```
pnpm run deploy
```

Note

Preview the build locally before deploying:

npmyarnpnpm

```
npm run preview
```

```
yarn run preview
```

```
pnpm run preview
```

## Custom entrypoints

TanStack Start uses `@tanstack/react-start/server-entry` as your default entrypoint. Create a custom server entrypoint to add additional Workers handlers such as [Queues](https://e8aee267.previews.developers.cloudflare.com/queues/) and [Cron Triggers](https://e8aee267.previews.developers.cloudflare.com/workers/configuration/cron-triggers/). This is also where you can add additional exports such as [Durable Objects](https://e8aee267.previews.developers.cloudflare.com/durable-objects/) and [Workflows](https://e8aee267.previews.developers.cloudflare.com/workflows/).

1. Create a custom server entrypoint file:  
```js  
import handler from "@tanstack/react-start/server-entry";  
// Export Durable Objects as named exports  
export { MyDurableObject } from "./my-durable-object";  
export default {  
	fetch: handler.fetch,  
	// Handle Queue messages  
	async queue(batch, env, ctx) {  
		for (const message of batch.messages) {  
			console.log("Processing message:", message.body);  
			message.ack();  
		}  
	},  
	// Handle Cron Triggers  
	async scheduled(event, env, ctx) {  
		console.log("Cron triggered:", event.cron);  
	},  
};  
```  
```ts  
import handler from "@tanstack/react-start/server-entry";  
// Export Durable Objects as named exports  
export { MyDurableObject } from "./my-durable-object";  
export default {  
	fetch: handler.fetch,  
	// Handle Queue messages  
	async queue(batch, env, ctx) {  
		for (const message of batch.messages) {  
			console.log("Processing message:", message.body);  
			message.ack();  
		}  
	},  
	// Handle Cron Triggers  
	async scheduled(event, env, ctx) {  
		console.log("Cron triggered:", event.cron);  
	},  
};  
```
2. Update your Wrangler configuration to point to your custom entrypoint:  
```jsonc  
{  
	"main": "src/server.ts",  
}  
```  
```toml  
main = "src/server.ts"  
```

### Test scheduled handlers locally

Test your scheduled handler locally using the `/cdn-cgi/handler/scheduled` endpoint:

```sh
curl "http://localhost:3000/cdn-cgi/handler/scheduled?cron=*+*+*+*+*"
```

Example: Using Workflows

Export a Workflow class from your custom entrypoint to run durable, multi-step tasks:

```js
import {
	WorkflowEntrypoint,
	WorkflowStep,
	WorkflowEvent,
} from "cloudflare:workers";

export class MyWorkflow extends WorkflowEntrypoint {
	async run(event, step) {
		const result = await step.do("process data", async () => {
			return `Processed: ${event.payload.input}`;
		});

		await step.sleep("wait", "10 seconds");

		await step.do("finalize", async () => {
			console.log("Workflow complete:", result);
		});
	}
}
```

```ts
import {
	WorkflowEntrypoint,
	WorkflowStep,
	WorkflowEvent,
} from "cloudflare:workers";

export class MyWorkflow extends WorkflowEntrypoint<Env> {
	async run(event: WorkflowEvent<{ input: string }>, step: WorkflowStep) {
		const result = await step.do("process data", async () => {
			return `Processed: ${event.payload.input}`;
		});

		await step.sleep("wait", "10 seconds");

		await step.do("finalize", async () => {
			console.log("Workflow complete:", result);
		});
	}
}
```

Add the Workflow configuration to your Wrangler configuration:

```jsonc
{
	"workflows": [
		{
			"name": "my-workflow",
			"binding": "MY_WORKFLOW",
			"class_name": "MyWorkflow",
		},
	],
}
```

```toml
[[workflows]]
name = "my-workflow"
binding = "MY_WORKFLOW"
class_name = "MyWorkflow"
```

Example: Using Service Bindings

Add a service binding to call another Worker's RPC methods from your TanStack Start application:

```jsonc
{
	"services": [
		{
			"binding": "AUTH_SERVICE",
			"service": "auth-worker",
		},
	],
}
```

```toml
[[services]]
binding = "AUTH_SERVICE"
service = "auth-worker"
```

Call the bound Worker's methods from a server function:

```js
import { createServerFn } from "@tanstack/react-start";
import { env } from "cloudflare:workers";

const verifyUser = createServerFn()
	.inputValidator((token) => token)
	.handler(async ({ data: token }) => {
		const result = await env.AUTH_SERVICE.verify(token);
		return result;
	});
```

```ts
import { createServerFn } from "@tanstack/react-start";
import { env } from "cloudflare:workers";

const verifyUser = createServerFn()
	.inputValidator((token: string) => token)
	.handler(async ({ data: token }) => {
		const result = await env.AUTH_SERVICE.verify(token);
		return result;
	});
```

## Bindings

Your TanStack Start application can be fully integrated with the Cloudflare Developer Platform, in both local development and in production, by using [bindings](https://e8aee267.previews.developers.cloudflare.com/workers/runtime-apis/bindings/).

Access bindings by [importing the env object](https://e8aee267.previews.developers.cloudflare.com/workers/runtime-apis/bindings/#importing-env-as-a-global) in your server-side code:

```js
import { createFileRoute } from "@tanstack/react-router";
import { createServerFn } from "@tanstack/react-start";
import { env } from "cloudflare:workers";

export const Route = createFileRoute("/")({
	loader: () => getData(),
	component: RouteComponent,
});

const getData = createServerFn().handler(() => {
	// Access bindings via env
	// For example: env.MY_KV, env.MY_BUCKET, env.AI, etc.
});

function RouteComponent() {
	// ...
}
```

```ts
import { createFileRoute } from "@tanstack/react-router";
import { createServerFn } from "@tanstack/react-start";
import { env } from "cloudflare:workers";

export const Route = createFileRoute("/")({
	loader: () => getData(),
	component: RouteComponent,
});

const getData = createServerFn().handler(() => {
	// Access bindings via env
	// For example: env.MY_KV, env.MY_BUCKET, env.AI, etc.
});

function RouteComponent() {
	// ...
}
```

Generate TypeScript types for your bindings based on your Wrangler configuration:

npmyarnpnpm

```
npm run cf-typegen
```

```
yarn run cf-typegen
```

```
pnpm run cf-typegen
```

With bindings, your application can be fully integrated with the Cloudflare Developer Platform, giving you access to compute, storage, AI and more.

### [Bindings](https://e8aee267.previews.developers.cloudflare.com/workers/runtime-apis/bindings/)

Access to compute, storage, AI and more.

### Use R2 in a server function

Add an [R2 bucket binding](https://e8aee267.previews.developers.cloudflare.com/r2/api/workers/workers-api-usage/#4-bind-your-bucket-to-a-worker) to your Wrangler configuration:

```jsonc
{
	"r2_buckets": [
		{
			"binding": "MY_BUCKET",
			"bucket_name": "<YOUR_BUCKET_NAME>",
		},
	],
}
```

```toml
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "<YOUR_BUCKET_NAME>"
```

Access the bucket in a server function:

```js
import { createServerFn } from "@tanstack/react-start";
import { env } from "cloudflare:workers";

const uploadFile = createServerFn({ method: "POST" })
	.validator((data) => data)
	.handler(async ({ data }) => {
		await env.MY_BUCKET.put(data.key, data.content);
		return { success: true };
	});

const getFile = createServerFn()
	.validator((key) => key)
	.handler(async ({ data: key }) => {
		const object = await env.MY_BUCKET.get(key);
		return object ? await object.text() : null;
	});
```

```ts
import { createServerFn } from "@tanstack/react-start";
import { env } from "cloudflare:workers";

const uploadFile = createServerFn({ method: "POST" })
	.validator((data: { key: string; content: string }) => data)
	.handler(async ({ data }) => {
		await env.MY_BUCKET.put(data.key, data.content);
		return { success: true };
	});

const getFile = createServerFn()
	.validator((key: string) => key)
	.handler(async ({ data: key }) => {
		const object = await env.MY_BUCKET.get(key);
		return object ? await object.text() : null;
	});
```

## Static prerendering

Prerender your application to static HTML at build time and serve as [static assets](https://e8aee267.previews.developers.cloudflare.com/workers/static-assets/).

```js
import { defineConfig } from "vite";
import { cloudflare } from "@cloudflare/vite-plugin";
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
	plugins: [
		cloudflare({ viteEnvironment: { name: "ssr" } }),
		tanstackStart({
			prerender: {
				enabled: true,
			},
		}),
		react(),
	],
});
```

```ts
import { defineConfig } from "vite";
import { cloudflare } from "@cloudflare/vite-plugin";
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
	plugins: [
		cloudflare({ viteEnvironment: { name: "ssr" } }),
		tanstackStart({
			prerender: {
				enabled: true,
			},
		}),
		react(),
	],
});
```

For more options, refer to [TanStack Start static prerendering ↗](https://tanstack.com/start/latest/docs/framework/react/guide/static-prerendering).

Note

Requires `@tanstack/react-start` v1.138.0 or later.

### Prerendering data sources

Caution

Prerendering runs at build time. It uses your local environment variables, secrets, and bindings storage data.

To prerender with production data, use [remote bindings](https://e8aee267.previews.developers.cloudflare.com/workers/local-development/#remote-bindings).

In CI environments, environment variables or secrets may not be available during the build. To make them accessible:

* Set `CLOUDFLARE_INCLUDE_PROCESS_ENV=true` in your CI environment and provide the required values as environment variables.
* If using [Workers Builds](https://e8aee267.previews.developers.cloudflare.com/workers/ci-cd/builds/), update your [build settings](https://e8aee267.previews.developers.cloudflare.com/workers/ci-cd/builds/configuration/#build-settings).

Was this helpful?

YesNo

## On this page

[![](https://e8aee267.previews.developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://e8aee267.previews.developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/workers/framework-guides/web-apps/tanstack-start/#page","headline":"TanStack Start · Cloudflare Workers docs","description":"Deploy a TanStack Start application to Cloudflare Workers.","url":"https://developers.cloudflare.com/workers/framework-guides/web-apps/tanstack-start/","inLanguage":"en","image":"https://developers.cloudflare.com/og-docs.png","dateModified":"2026-08-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["full-stack"]}
```
