---
name: tanstack-start-project-setup
description: Set up and configure TanStack Start projects. Use when creating new projects, configuring the router, setting up TanStack Query integration, or configuring build settings.
license: Apache-2.0
metadata:
author: tanstack
version: "1.0"
---
# TanStack Start project setup
Use the existing starter's package.json, vite.config.ts, tsconfig.json, and netlify.toml as the source of truth. These projects use Vite and the Start Vite plugin, not Vinxi, app.config.ts, or a server preset. Do not replace the project's framework or assume scripts that are not defined.
## Build configuration
This complete Vite configuration works with the Vite 7 and 8 versions used by the starters. It uses Vite's standard alias option. Basic already uses Vite 8's native resolve.tsconfigPaths; retain that option there. Older starters use vite-tsconfig-paths; keep it unless replacing it with an equivalent supported alias configuration.
```ts file=vite.config.ts
import { fileURLToPath } from 'node:url'
import { defineConfig } from 'vite'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
import netlify from '@netlify/vite-plugin-tanstack-start'
export default defineConfig({
resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } },
plugins: [tailwindcss(), netlify(), tanstackStart(), react()],
})
```
Start must precede the React plugin. Put Content Collections before Start when the project uses that optional integration. The Netlify adapter generates the server entry; don't configure a separate .output/server functions directory.
## Router and server errors
Create a router per request. Register its type so links and route parameters can be checked. Set the default error component on the router, not only the root route: child-route SSR failures select a route-local error component or the router default. Keep internal error details off the page.
```tsx file=src/router.tsx
import { createRouter, useRouter, type ErrorComponentProps } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'
function SafeErrorPage({ reset }: ErrorComponentProps) {
const router = useRouter()
return (
<main>
<h1>This page couldn’t load</h1>
<p role="alert">Please try again or return home.</p>
<button onClick={() => { void router.invalidate(); reset() }}>Try again</button>
<a href="/">Go home</a>
</main>
)
}
export function getRouter() {
return createRouter({
routeTree,
scrollRestoration: true,
defaultPreloadStaleTime: 0,
defaultErrorComponent: SafeErrorPage,
})
}
declare module '@tanstack/react-router' {
interface Register { router: ReturnType<typeof getRouter> }
}
```
Retain an existing branded safe error component when one is supplied. src/routeTree.gen.ts is generated by dev/build and should not be edited. Root document and route examples are in the tanstack-start-routes skill.
## TypeScript and commands
Keep strict mode, ES2022, Bundler resolution, react-jsx, noEmit, and the @/* source alias. Keep verbatimModuleSyntax disabled for Start's server/client transforms. Build/dev must run once before tsc so route and optional content types exist. Generated content imports also require the path mapping described in the content-collections skill.
Check that React Router and Start resolve the same @tanstack/router-core version. Separate core versions can prevent Start's API-route type extensions from reaching React Router, causing TypeScript to reject the server option even when a Vite build succeeds.
Use Node 22.13+ on the Node 22 line, Node 24, or Node 26+ across this repository. Start requires at least 22.12; the newer lint/test tooling raises the Node 22 floor to 22.13. Check installed engines and peer dependencies during upgrades. Keep exact package versions and remove unused/duplicate entries when updating a starter.
Every starter defines npm run dev and npm run build. Only use npm run typecheck, lint, test, preview, or format when package.json defines them; otherwise the installed tools can be called with npx --no-install tsc --noEmit or npx --no-install vite preview. A Vite build alone does not type-check.
The Netlify build configuration is:
```toml
[build]
command = "vite build"
publish = "dist/client"
[dev]
command = "npm run dev"
targetPort = 3000
port = 8888
```
Keep credentials in server functions/server handlers, not VITE_* variables, route-loader results, or browser modules. Loaders also run during client navigation. Use the relevant Netlify data/auth skill when adding those features; no database or authentication is part of project setup by default.
TanStack Query is optional. If needed, install compatible query and router SSR integration packages, create QueryClient inside getRouter(), declare root context, and wire provider plus dehydration/hydration together. A provider alone does not implement SSR cache transfer. Follow the installed integration's documentation rather than adding a module-level user-data cache.
Reference: https://tanstack.com/start/latest/docs/framework/react/build-from-scratch