tanstack-start-project-setup
$
npx mdskill add netlify/swar-templates/tanstack-start-project-setupInitialize TanStack Start projects with router, query, and build configs.
- Creates new React applications with integrated routing and query.
- Depends on TanStack Router, Vinxi, Vite, and TypeScript.
- Analyzes project goals to select appropriate configuration templates.
- Generates complete project structures including server functions and layouts.
SKILL.md
.github/skills/tanstack-start-project-setupView on GitHub ↗
---
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
TanStack Start is a full-stack React framework built on TanStack Router, Vinxi, and Vite.
## When to Use
- Creating a new TanStack Start project
- Configuring router settings
- Setting up TanStack Query
- Adding TypeScript configuration
- Configuring for Netlify deployment
## Quick Start
```bash
# Create new project
npx create-tanstack-start@latest my-app
# Or with specific template
npx create-tanstack-start@latest my-app --template basic
```
## Project Structure
```
my-app/
├── src/
│ ├── routes/
│ │ ├── __root.tsx # Root layout
│ │ ├── index.tsx # Home page (/)
│ │ └── ...
│ ├── server/
│ │ └── *.functions.ts # Server functions
│ ├── components/
│ ├── lib/
│ ├── router.tsx # Router configuration
│ └── routeTree.gen.ts # Auto-generated
├── public/
├── app.config.ts # TanStack Start config
├── package.json
├── tsconfig.json
└── netlify.toml # Netlify deployment
```
## Essential Files
### app.config.ts
```typescript
// app.config.ts
import { defineConfig } from '@tanstack/react-start/config';
export default defineConfig({
// Vite configuration
vite: {
// Add Vite plugins here
plugins: [],
},
// Server configuration
server: {
// Server preset (netlify, vercel, node, etc.)
preset: 'netlify',
},
// Router configuration
tsr: {
// Route file location
routesDirectory: './src/routes',
// Generated route tree location
generatedRouteTree: './src/routeTree.gen.ts',
},
});
```
### router.tsx
```tsx
// src/router.tsx
import { createRouter } from '@tanstack/react-router';
import { routeTree } from './routeTree.gen';
export function getRouter() {
const router = createRouter({
routeTree,
// Enable scroll restoration
scrollRestoration: true,
// Preload on hover
defaultPreload: 'intent',
// Preload stale time
defaultPreloadStaleTime: 0,
// Default error component
defaultErrorComponent: ({ error }) => (
<div>Error: {error.message}</div>
),
// Default pending component
defaultPendingComponent: () => <div>Loading...</div>,
// Default not found component
defaultNotFoundComponent: () => <div>Not Found</div>,
});
return router;
}
// Type registration for full type safety
declare module '@tanstack/react-router' {
interface Register {
router: ReturnType<typeof getRouter>;
}
}
```
### Root Route (__root.tsx)
```tsx
// src/routes/__root.tsx
import {
Outlet,
createRootRoute,
HeadContent,
Scripts,
} from '@tanstack/react-router';
import type { ReactNode } from 'react';
export const Route = createRootRoute({
head: () => ({
meta: [
{ charSet: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ title: 'My TanStack Start App' },
{ name: 'description', content: 'Built with TanStack Start' },
],
links: [
{ rel: 'stylesheet', href: '/styles.css' },
{ rel: 'icon', href: '/favicon.ico' },
],
}),
component: RootComponent,
});
function RootComponent() {
return (
<html lang="en">
<head>
<HeadContent />
</head>
<body>
<Outlet />
<Scripts />
</body>
</html>
);
}
```
## TanStack Query Integration
### Installation
```bash
npm install @tanstack/react-query
```
### Setup
```tsx
// src/router.tsx
import { createRouter } from '@tanstack/react-router';
import { QueryClient } from '@tanstack/react-query';
import { routeTree } from './routeTree.gen';
export function getRouter() {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60, // 1 minute
gcTime: 1000 * 60 * 5, // 5 minutes
},
},
});
const router = createRouter({
routeTree,
context: {
queryClient,
},
});
return router;
}
declare module '@tanstack/react-router' {
interface Register {
router: ReturnType<typeof getRouter>;
}
}
```
### Root with Query Provider
```tsx
// src/routes/__root.tsx
import { QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
export const Route = createRootRouteWithContext<{
queryClient: QueryClient;
}>()({
component: RootComponent,
});
function RootComponent() {
const { queryClient } = Route.useRouteContext();
return (
<QueryClientProvider client={queryClient}>
<html lang="en">
<head>
<HeadContent />
</head>
<body>
<Outlet />
<Scripts />
<ReactQueryDevtools />
</body>
</html>
</QueryClientProvider>
);
}
```
## TypeScript Configuration
```json
// tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"noEmit": true,
"isolatedModules": true,
"esModuleInterop": true,
"skipLibCheck": true,
"paths": {
"~/*": ["./src/*"]
}
},
"include": ["src/**/*", "app.config.ts"],
"exclude": ["node_modules"]
}
```
## Netlify Deployment
### netlify.toml
```toml
[build]
command = "npm run build"
publish = ".output/public"
[build.environment]
NODE_VERSION = "20"
# Functions directory (auto-configured by TanStack Start)
[functions]
directory = ".output/server"
```
### app.config.ts for Netlify
```typescript
// app.config.ts
import { defineConfig } from '@tanstack/react-start/config';
export default defineConfig({
server: {
preset: 'netlify',
},
});
```
## Environment Variables
### .env Files
```bash
# .env (local development)
DATABASE_URL=postgres://localhost:5432/mydb
VITE_APP_NAME=My App
# .env.production (production)
DATABASE_URL=postgres://prod-server:5432/mydb
VITE_APP_NAME=My App
```
### Accessing Variables
```typescript
// Server-side (server functions, loaders on server)
const dbUrl = process.env.DATABASE_URL;
// Client-side (must be prefixed with VITE_)
const appName = import.meta.env.VITE_APP_NAME;
```
## CSS/Styling Setup
### Tailwind CSS
```bash
npm install tailwindcss @tailwindcss/vite
```
```typescript
// app.config.ts
import { defineConfig } from '@tanstack/react-start/config';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
vite: {
plugins: [tailwindcss()],
},
});
```
```css
/* src/styles.css */
@import 'tailwindcss';
```
### CSS Modules
```tsx
// Component.tsx
import styles from './Component.module.css';
export function Component() {
return <div className={styles.container}>Hello</div>;
}
```
## Development Scripts
```json
// package.json
{
"scripts": {
"dev": "vinxi dev",
"build": "vinxi build",
"start": "vinxi start",
"lint": "eslint src/",
"typecheck": "tsc --noEmit"
}
}
```
## Recommended Package.json
```json
{
"name": "my-tanstack-app",
"type": "module",
"scripts": {
"dev": "vinxi dev",
"build": "vinxi build",
"start": "vinxi start"
},
"dependencies": {
"@tanstack/react-query": "^5.0.0",
"@tanstack/react-router": "^1.0.0",
"@tanstack/react-start": "^1.0.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"vinxi": "^0.5.0",
"zod": "^3.23.0"
},
"devDependencies": {
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"typescript": "^5.6.0"
}
}
```
## Database Setup (Drizzle)
```bash
npm install drizzle-orm@beta @netlify/database
npm install -D drizzle-kit@beta
```
```typescript
// drizzle.config.ts
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
dialect: 'postgresql',
schema: './db/schema.ts',
out: 'netlify/database/migrations',
});
```
```typescript
// db/index.ts
import { drizzle } from 'drizzle-orm/netlify-db';
import * as schema from './schema';
export const db = drizzle({ schema });
```
## Common Configurations
### Custom 404 Page
```tsx
// src/routes/__root.tsx
export const Route = createRootRoute({
notFoundComponent: () => (
<div className="not-found">
<h1>404 - Page Not Found</h1>
<Link to="/">Go Home</Link>
</div>
),
});
```
### Global Error Boundary
```tsx
// src/routes/__root.tsx
export const Route = createRootRoute({
errorComponent: ({ error, reset }) => (
<div className="error-page">
<h1>Something went wrong</h1>
<p>{error.message}</p>
<button onClick={reset}>Try Again</button>
</div>
),
});
```
### Loading States
```tsx
// src/routes/__root.tsx
export const Route = createRootRoute({
pendingComponent: () => (
<div className="loading">
<span className="spinner" />
Loading...
</div>
),
});
```
## Checklist for New Projects
- [ ] Create project with `create-tanstack-start`
- [ ] Configure `app.config.ts` with Netlify preset
- [ ] Set up TypeScript paths (`~/`)
- [ ] Configure TanStack Query if needed
- [ ] Set up CSS solution (Tailwind recommended)
- [ ] Create `.env` for local development
- [ ] Configure `netlify.toml` for deployment
- [ ] Set up database if needed (Drizzle + Netlify Database)
- [ ] Add ESLint configuration
- [ ] Set environment variables in Netlify dashboard
More from netlify/swar-templates
- content-collectionsUse content-collections for type-safe content management with markdown files. Use when building blogs, documentation sites, or any content-driven pages with frontmatter and markdown.
- netlify-forms-tanstackHandle Netlify Forms in TanStack Start. Use when implementing contact forms, signup forms, or any form submission handling on Netlify-hosted TanStack Start sites.
- netlify-identity-tanstack-startUpgrade a stock TanStack Start project to use Netlify Identity for authentication via the @netlify/identity package. Use this skill whenever the user wants to add Netlify Identity auth to a TanStack Start app, integrate login/signup into TanStack Start, protect routes or server functions with Netlify Identity, add role-based access control, or wire up Netlify Identity webhooks. Also use when the user mentions '@netlify/identity', 'nf_jwt', or asks about auth for TanStack Start on Netlify. Covers SSR pages, SPA pages, API routes, server functions, middleware, route guards, role-based access, identity webhooks, and client-side auth state.
- tanstack-start-api-routesCreate API routes (server routes) in TanStack Start for handling HTTP requests. Use when building REST APIs, webhooks, or any HTTP endpoint that returns data rather than rendering a page.
- tanstack-start-loadersLoad data for TanStack Start routes using beforeLoad and loader functions. Use when fetching data for pages, implementing route guards, or setting up route context. IMPORTANT - Loaders should call server functions for data access.
- tanstack-start-routesCreate and manage routes in TanStack Start using file-based routing. Use when adding new pages, configuring layouts, setting up nested routes, or working with route parameters.
- tanstack-start-server-functionsCreate server functions in TanStack Start for server-side logic callable from anywhere. Use for database access, API calls with secrets, mutations, server-only code, or when you must use .inputValidator(...) for createServerFn inputs.
- tanstack-start-typesafe-routingImplement type-safe navigation and links in TanStack Start. Use when creating links, navigating programmatically, working with search params, or accessing route parameters with full TypeScript support.