1---
2title: TanStack Start
3description: Deploy TanStack Start to Prisma Compute with Prisma.Website.TanStackStart — React or Solid SSR on Bun, with native Vite dev locally.
4sidebar:
5 order: 8
6---
7
8import { Code, Tabs, TabItem } from "@astrojs/starlight/components";
9
10export const devDeps = "@alchemy.run/frontend-frameworks @vercel/nft";
11
12`Prisma.Website.TanStackStart` builds [TanStack Start](https://tanstack.com/start)
13for React or Solid through your project's Vite pipeline. The shared
14Node target wraps its fetch handler as an HTTP server; SSR and client
15assets run on **Bun in Prisma Compute** from a `tar.gz` upload. There
16is no Docker image or registry.
17
18## Install
19
20Install the build-time integration; the resource loads `/tanstack-start`
21and `/tanstack-start/node` from your project:
22
23<Tabs syncKey="pkgManager">
24 <TabItem label="bun" icon="bun"><Code code={`bun add -d ${devDeps}`} lang="sh" /></TabItem>
25 <TabItem label="npm" icon="npm"><Code code={`npm install -D ${devDeps}`} lang="sh" /></TabItem>
26 <TabItem label="pnpm" icon="pnpm"><Code code={`pnpm add -D ${devDeps}`} lang="sh" /></TabItem>
27 <TabItem label="yarn" icon="seti:yarn"><Code code={`yarn add -D ${devDeps}`} lang="sh" /></TabItem>
28</Tabs>
29
30## Configure Vite
31
32Keep the framework plugin and normal Vite plugins. For React:
33
34```typescript
35// vite.config.ts
36import tailwindcss from "@tailwindcss/vite";
37import { tanstackStart } from "@tanstack/react-start/plugin/vite";
38import viteReact from "@vitejs/plugin-react";
39import { defineConfig } from "vite";
40
41export default defineConfig({
42 plugins: [tailwindcss(), tanstackStart(), viteReact()],
43});
44```
45
46The integration drives `builder.buildApp()` and makes the SSR bundle
47self-contained. No deployment adapter is required.
48
49:::caution[Remove the Cloudflare Vite plugin]
50If the scaffold includes `@cloudflare/vite-plugin`, remove it. It
51builds for workerd, not the Node-compatible target hosted on Prisma:
52
53```diff lang="typescript"
54-import { cloudflare } from "@cloudflare/vite-plugin";
55import { tanstackStart } from "@tanstack/react-start/plugin/vite";
56import viteReact from "@vitejs/plugin-react";
57import { defineConfig } from "vite";
58
59export default defineConfig({
60- plugins: [cloudflare({ viteEnvironment: { name: "ssr" } }), tanstackStart(), viteReact()],
61+ plugins: [tanstackStart(), viteReact()],
62});
63```
64
65:::
66
67## Declare the Website
68
69```typescript
70// alchemy.run.ts
71import * as Prisma from "alchemy/Prisma";
72
73export const Website = Prisma.Website.TanStackStart("Website", {
74 rootDir: "./app",
75});
76```
77
78Omit `rootDir` for an app at `.`. Live deploy creates a database-less
79Prisma project if `project` is omitted; pass an existing project to
80share it with other apps.
81
82## Add it to the Stack
83
84```typescript
85// alchemy.run.ts
86import * as Alchemy from "alchemy";
87import * as Effect from "effect/Effect";
88
89export default Alchemy.Stack(
90 "MyTanStackSite",
91 { providers: Prisma.providers(), state: Alchemy.localState() },
92 Effect.gen(function* () {
93 const site = yield* Website;
94 return { url: site.url };
95 }),
96);
97```
98
99Client assets are served first; misses go to SSR, server routes, or
100server functions. `site.url` is the Compute endpoint on deploy.
101
102## Add environment variables
103
104```diff lang="typescript"
105export const Website = Prisma.Website.TanStackStart("Website", {
106 rootDir: "./app",
107+ env: { API_BASE: "https://api.example.com" },
108});
109```
110
111`env` is applied before build and dev and passed to Compute. Vite
112inlines `VITE_*` values into the browser bundle; keep secrets out of
113those keys. Sibling outputs can feed `env` inside the Stack generator.
114
115## Read the environment in a server function
116
117```typescript
118// src/routes/index.tsx
119import { createServerFn } from "@tanstack/react-start";
120
121const getApiBase = createServerFn({ method: "GET" }).handler(() => ({
122 apiBase: process.env.API_BASE ?? "unset",
123}));
124```
125
126Server functions run on Bun and read `process.env`.
127
128## Read the environment in a server route
129
130```typescript
131// src/routes/api.hello.ts
132import { createFileRoute } from "@tanstack/react-router";
133
134export const Route = createFileRoute("/api/hello")({
135 server: {
136 handlers: {
137 GET: () => new Response(process.env.API_BASE ?? "unset"),
138 },
139 },
140});
141```
142
143Server routes use the same process environment.
144
145## Build configuration
146
147Your `vite.config.ts` is the build configuration. Keep Vite's default
148output directory, `dist`; the integration reads `dist/server` and
149`dist/client`. Static files are served by Compute, not deployed as an
150independent CDN site.
151
152## Local dev
153
154`bun alchemy dev` starts TanStack Start's native Vite server with HMR
155and creates no Prisma resources for the Website. Opt into live deployment
156during dev explicitly:
157
158```typescript
159export const Website = Prisma.Website.TanStackStart("Website").pipe(
160 Alchemy.remote(),
161);
162```
163
164## Custom domain
165
166```typescript
167const site = yield* Prisma.Website.TanStackStart("Web", {
168 domain: "app.example.com",
169});
170```
171
172`Prisma.CustomDomain` requires the app to be on the current default
173branch. Configure returned DNS records yourself and verify status before
174cutover; see [Custom domains](/prisma/frontend/websites#custom-domains).
175
176## Where next
177
178- [TanStack Start API](/providers/prisma/website/tanstackstart).
179- [TanStack Start example](https://github.com/alchemy-run/alchemy/tree/main/examples/prisma-website-tanstack-start).
180- [Websites](/prisma/frontend/websites) and [Compute apps](/prisma/compute/apps).