Skip to content

Commit a83cab9

Browse files
Update TanStack Workers guide to use the Cloudflare Vite plugin
Note: this is a temporary update to the guide (which is currently incorrect), we're working on enabling C3 to generate TanStack applications to streamline the process for developers, once that's ready we'll update again this guide accordingly
1 parent 2d5bd52 commit a83cab9

File tree

1 file changed

+105
-173
lines changed
  • src/content/docs/workers/framework-guides/web-apps

1 file changed

+105
-173
lines changed

src/content/docs/workers/framework-guides/web-apps/tanstack.mdx

Lines changed: 105 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -8,224 +8,156 @@ tags: ["full-stack"]
88
description: Create a TanStack Start application and deploy it to Cloudflare Workers with Workers Assets.
99
---
1010

11-
import { WranglerConfig, Steps, PackageManagers, Details } from "~/components";
11+
import {
12+
Badge,
13+
Description,
14+
InlineBadge,
15+
Render,
16+
PackageManagers,
17+
} from "~/components";
1218

13-
## What is TanStack Start?
19+
In this guide, you will create a new [TanStack Start](https://tanstack.com/start) application and deploy it to Cloudflare Workers (with the new [Workers Assets](/workers/static-assets/)).
1420

15-
TanStack Start is a full-stack React framework powered by TanStack Router. It provides a full-document SSR, streaming, server functions, bundling, and more using Vite and modern web standards.
21+
## 1. Set up a new project
1622

17-
## Create a new TanStack Start
23+
### Create the project
1824

19-
TanStack Start Beta has significantly improved Cloudflare compatibility compared to the Alpha version, making deployment and development much more straightforward.
25+
Start by creating a new project using the official TanStack CLI:
2026

21-
<Steps>
27+
<PackageManagers
28+
type="create"
29+
pkg="@tanstack/start@latest"
30+
args="my-tanstack-app"
31+
/>
2232

23-
1. **Create a new TanStack Start project**
33+
After setting up your project, change your directory by running the following command:
2434

25-
```sh
26-
npx gitpick TanStack/router/tree/main/examples/react/start-basic start-basic
27-
cd start-basic
28-
npm install
29-
```
30-
31-
<Details header="How is this project set up?">
32-
This command will clone the TanStack Start basic project to your local machine, change directory to the project, and install the dependencies. TanStack [provides other examples](https://tanstack.com/start/latest/docs/framework/react/quick-start#examples) that you can use by replacing `start-basic` with the example you want to use.
33-
</Details>
35+
```sh
36+
cd my-tanstack-app
37+
```
3438

35-
2. **Develop locally**
39+
### Install the Cloudflare dependencies
3640

37-
After creating your project, run the following command in your project directory to start a local development server. By default this starts a local development server on `http://localhost:3000/`
41+
Inside the project's directory install the Cloudflare development dependencies:
3842

39-
<PackageManagers type="run" args="dev" />
43+
<PackageManagers pkg="@cloudflare/vite-plugin wrangler" dev />
4044

41-
</Steps>
45+
### Create a `wrangler.jsonc` file
4246

43-
## Preparing for Deployment to Cloudflare Workers
47+
Create a `wrangler.jsonc` file with the following:
4448

45-
Whether you created a new TanStack Start project or are using an existing project, you'll need to make some changes to prepare for deployment to Cloudflare Workers.
49+
```json
50+
{
51+
"$schema": "node_modules/wrangler/config-schema.json",
52+
"name": "my-tanstack-app",
53+
"compatibility_date": "2025-09-02",
54+
"compatibility_flags": ["nodejs_compat"],
55+
"main": "@tanstack/react-start/server-entry"
56+
}
57+
```
4658

47-
<Steps>
59+
### Add Cloudflare scripts to the `package.json` file
4860

49-
1. **Configure Vite for Cloudflare compatibility**
61+
Add the following scripts to your `package.json` file:
5062

51-
Update your `vite.config.ts` file to use the `cloudflare-module` target for a compatible build:
63+
```json
64+
"deploy": "wrangler deploy",
65+
"cf-typegen": "wrangler types"
66+
```
5267

53-
```ts title="vite.config.ts" {14}
54-
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
55-
import { defineConfig } from "vite";
56-
import tsConfigPaths from "vite-tsconfig-paths";
68+
- `deploy`: this script can be to deploy your application after you've built it
5769

58-
export default defineConfig({
59-
server: {
60-
port: 3000,
61-
},
62-
plugins: [
63-
tsConfigPaths({
64-
projects: ["./tsconfig.json"],
65-
}),
66-
tanstackStart({
67-
target: "cloudflare-module", // Key configuration for Cloudflare compatibility
68-
}),
69-
],
70-
});
71-
```
70+
- `cf-typegen`: generate Cloudflare TypeScript types for your project based on your configuration
7271

73-
This single configuration change is all that's needed to make your TanStack Start application compatible with Cloudflare Workers.
72+
Note that there are already three relevant scripts that the TanStack CLI defined for you: `dev` and `serve`. Which respectively allow you to start a local Vite dev server
73+
to develop locally your application, build your application (so that it can be deployed) and start a local preview server that you can use to validate your build application
74+
before deploying it.
7475

75-
2. **Add a Wrangler file**
76+
### Update the `vite.config.ts` file
7677

77-
Create a `wrangler.jsonc` or `wrangler.toml` file in the root of your project, `wrangler.jsonc` is the recommended approach. This file is used to configure the Cloudflare Workers deployment.
78+
Next you need to update update the Vite configuration file to use the Cloudflare plugin:
7879

79-
<WranglerConfig>
80+
```diff lang="ts"
81+
import viteReact from '@vitejs/plugin-react'
82+
import viteTsConfigPaths from 'vite-tsconfig-paths'
83+
import tailwindcss from '@tailwindcss/vite'
84+
+import { cloudflare } from '@cloudflare/vite-plugin';
8085

81-
```json
82-
{
83-
"$schema": "node_modules/wrangler/config-schema.json",
84-
"name": "my-start-app",
85-
"main": ".output/server/index.mjs",
86-
"compatibility_date": "$today",
87-
"compatibility_flags": ["nodejs_compat"],
88-
"assets": {
89-
"directory": ".output/public"
90-
},
91-
"observability": {
92-
"enabled": true
93-
},
94-
"kv_namespaces": [
95-
{
96-
"binding": "CACHE",
97-
"id": "<Your KV ID>"
98-
}
99-
]
100-
}
101-
```
86+
const config = defineConfig({
87+
plugins: [
88+
tailwindcss(),
89+
tanstackStart(),
90+
viteReact(),
91+
+ cloudflare({ viteEnvironment: { name: 'ssr' } }),
92+
],
93+
+ environments: {
94+
+ ssr: {
95+
+ optimizeDeps: {
96+
+ exclude: ['@tanstack/react-devtools']
97+
+ }
98+
+ }
99+
+ }
100+
})
101+
```
102102

103-
</WranglerConfig>
103+
:::note
104104

105-
Note that the `directory` key is set to `.output/public`, which is the folder that will be filled with the build output. Additionally, the `main` key is set to `.output/server/index.mjs`, indicating to Cloudflare Workers where to locate the entry point for your application. The `kv_namespaces` section shows an example of how to configure a KV namespace binding.
105+
The `optimizeDeps` setting here is a temporary workaround and won't be necessary with future TanStack Start releases.
106106

107-
3. **Add deployment scripts to package.json**
107+
:::
108108

109-
Add the following scripts to your `package.json` file to streamline deployment and type generation:
109+
## 2. Develop locally
110110

111-
```json title="package.json
112-
{
113-
"scripts": {
114-
...
115-
"deploy": "npm run build && wrangler deploy",
116-
"cf-typegen": "wrangler types --env-interface Env"
117-
}
118-
}
119-
```
111+
After you have created your project, run the following command in the project directory to start a local server. This will allow you to preview your project locally during development.
120112

121-
The `deploy` script combines building and deploying in one command, while `cf-typegen` generates TypeScript types for your Cloudflare bindings.
122-
123-
4. **Build the application**
113+
<PackageManagers type="run" args="dev" />
124114

125-
You must build your application before deploying it to Cloudflare Workers.
115+
## 3. Deploy your Project
126116

127-
<PackageManagers type="run" args={"build"} />
117+
Your project can be deployed to a `*.workers.dev` subdomain or a [Custom Domain](/workers/configuration/routing/custom-domains/), from your own machine or from any CI/CD system, including [Cloudflare's own](/workers/ci-cd/builds/).
128118

129-
5. **Deploy the application**
119+
The following command will build and deploy your project. If you're using CI, ensure you update your ["deploy command"](/workers/ci-cd/builds/configuration/#build-settings) configuration appropriately.
130120

131-
You can now use the deploy script to build and deploy your application in one command:
121+
<PackageManagers type="run" args="deploy" />
132122

133-
<PackageManagers type="run" args={"deploy"} />
134-
135-
Alternatively, you can still deploy directly with Wrangler:
136-
137-
```sh
138-
npx wrangler deploy
139-
```
140-
141-
</Steps>
142-
143-
## Using Cloudflare Bindings
144-
145-
<Steps>
146-
147-
1. **Generate TypeScript types for your bindings**
148-
149-
Before using Cloudflare bindings in your code, generate the TypeScript types to ensure proper type safety:
150-
151-
<PackageManagers type="run" args={"cf-typegen"} />
152-
153-
This command reads your `wrangler.jsonc` configuration and generates an `Env` interface with all your configured bindings.
154-
155-
2. **Create a helper function to get access to Cloudflare bindings**
156-
157-
Create a helper function named `bindings.ts` in the `src/utils` folder (create the folder if it doesn't exist), and paste in the below code. The example assumes you have a KV namespace with a binding name of `CACHE` already created in your account and added to the wrangler file.
158-
159-
160-
```ts title="src/utils/bindings.ts"
161-
162-
let cachedEnv: Env | null = null;
163-
164-
// This gets called once at startup when running locally
165-
const initDevEnv = async () => {
166-
const { getPlatformProxy } = await import("wrangler");
167-
const proxy = await getPlatformProxy();
168-
cachedEnv = proxy.env as unknown as Env;
169-
};
170-
171-
if (import.meta.env.DEV) {
172-
await initDevEnv();
173-
}
174-
175-
/**
176-
* Will only work when being accessed on the server. Obviously, CF bindings are not available in the browser.
177-
* @returns
178-
*/
179-
export function getBindings(): Env {
180-
if (import.meta.env.DEV) {
181-
if (!cachedEnv) {
182-
throw new Error(
183-
"Dev bindings not initialized yet. Call initDevEnv() first."
184-
);
185-
}
186-
return cachedEnv;
187-
}
123+
---
188124

189-
return process.env as unknown as Env;
190-
}
191-
```
125+
## Bindings
192126

193-
<Details header="How is this code working?">
194-
The helper function uses [getPlatformProxy](/workers/wrangler/api/#getplatformproxy) method from wrangler to provide access to your Cloudflare bindings during local development. The bindings are cached at startup for better performance. In production, bindings are accessed via `process.env`. Make sure you've run `npm run cf-typegen` to generate the `Env` types that this code references.
195-
</Details>
127+
Your TanStack Start application can be fully integrated with the Cloudflare Developer Platform, in both local development and in production, by using product bindings.
196128

197-
3. **Example using a Cloudflare Binding in Server Functions**
129+
You can use bindings simply by [importing the `env` object](https://developers.cloudflare.com/workers/runtime-apis/bindings/#importing-env-as-a-global) and using it from your server
130+
side code.
198131

199-
Now that you have a helper function to get access to your Cloudflare bindings, you can use them in your server functions.
132+
For example in the following way:
200133

201-
Remember bindings are only available on the server.
134+
```tsx
135+
import { createFileRoute } from "@tanstack/react-router";
136+
import { createServerFn } from "@tanstack/react-start";
137+
import { env } from "cloudflare:workers";
202138

203-
```ts
204-
import { createServerFn } from "@tanstack/react-start";
205-
import { getBindings } from "~/utils/bindings";
139+
export const Route = createFileRoute("/")({
140+
loader: () => getData(),
141+
component: RouteComponent,
142+
});
206143

207-
const personServerFn = createServerFn({ method: "GET" })
208-
.validator((d: string) => d)
209-
.handler(async ({ data: name }) => {
210-
const env = getBindings();
211-
let growingAge = Number((await env.CACHE.get("age")) || 0);
212-
growingAge++;
213-
await env.CACHE.put("age", growingAge.toString());
214-
return { name, randomNumber: growingAge };
215-
});
216-
```
144+
const getData = createServerFn().handler(() => {
145+
// Use env here
146+
});
217147

218-
A special thanks to GitHub user [backpine](https://github.com/backpine) for the code that supports Cloudflare Bindings in TanStack Start, which is demonstrated in their [TanStack Start Beta on Cloudflare example](https://github.com/backpine/tanstack-start-beta-on-cloudflare).
148+
function RouteComponent() {
149+
// ...
150+
}
151+
```
219152

220-
</Steps>
153+
:::note
221154

222-
## Environment Handling
155+
Running the `cf-typegen` script:
223156

224-
The TanStack Start Beta version provides seamless environment handling:
157+
<PackageManagers type="run" args="cf-typegen" />
225158

226-
- **Development**: Bindings are accessed via [`getPlatformProxy()`](/workers/wrangler/api/#getplatformproxy) from Wrangler and cached at startup
227-
- **Production**: Bindings are accessed via [`process.env`](/workers/runtime-apis/nodejs/process/#processenv)
159+
Will populate the `env` object with the various bindings based on your configuration.
228160

229-
This approach ensures your bindings are properly typed throughout your project and provides a smooth development experience.
161+
:::
230162

231-
By following the steps above, you will have deployed your TanStack Start application to Cloudflare Workers.
163+
<Render file="frameworks-bindings" product="workers" />

0 commit comments

Comments
 (0)