Documentation Index
Fetch the complete documentation index at: https://mintlify.com/TanStack/router/llms.txt
Use this file to discover all available pages before exploring further.
Deployment
TanStack Start can be deployed to various hosting platforms. This guide covers deployment strategies and platform-specific configurations.
Build Process
Before deploying, build your application:
This creates optimized production bundles in the .output directory.
Deployment Targets
TanStack Start uses Nitro as its server engine, supporting multiple deployment targets.
Node.js Server
Deploy as a standalone Node.js application:
Configuration
// vite.config.ts
import { defineConfig } from 'vite'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { nitro } from 'nitro/vite'
export default defineConfig({
plugins: [
tanstackStart(),
nitro(),
],
})
Build and Run
# Build
npm run build
# Run production server
node .output/server/index.mjs
Environment Variables
# .env.production
PORT=3000
NODE_ENV=production
DATABASE_URL=postgres://...
Docker Deployment
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.output /app/.output
COPY --from=builder /app/package*.json /app/
EXPOSE 3000
CMD ["node", ".output/server/index.mjs"]
Build and run:
docker build -t my-app .
docker run -p 3000:3000 my-app
Cloudflare Workers
Deploy to Cloudflare’s edge network:
Configuration
// vite.config.ts
import { defineConfig } from 'vite'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { cloudflare } from '@cloudflare/vite-plugin'
export default defineConfig({
plugins: [
cloudflare({ viteEnvironment: { name: 'ssr' } }),
tanstackStart(),
],
})
Deploy
npm run build
npx wrangler deploy
wrangler.toml
name = "my-tanstack-app"
main = ".output/server/index.mjs"
compatibility_date = "2024-01-01"
[site]
bucket = ".output/public"
[[kv_namespaces]]
binding = "MY_KV"
id = "your-kv-id"
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "my-bucket"
Using Cloudflare Bindings
import { createServerFn } from '@tanstack/react-start'
export const getData = createServerFn({ method: 'GET' }).handler(
async ({ context }) => {
// Access Cloudflare bindings
const env = context.cloudflare.env
const value = await env.MY_KV.get('key')
return { value }
},
)
Vercel
Deploy to Vercel’s platform:
Configuration
// vercel.json
{
"buildCommand": "npm run build",
"outputDirectory": ".output/public",
"installCommand": "npm install"
}
Deploy
# Install Vercel CLI
npm i -g vercel
# Deploy
vercel
# Production deployment
vercel --prod
Environment Variables
Add environment variables in the Vercel dashboard:
- Settings → Environment Variables
- Add variables for each environment (Production, Preview, Development)
Netlify
Deploy to Netlify:
netlify.toml
[build]
command = "npm run build"
publish = ".output/public"
functions = ".output/server"
[[redirects]]
from = "/*"
to = "/.netlify/functions/server"
status = 200
Deploy
# Install Netlify CLI
npm i -g netlify-cli
# Deploy
netlify deploy
# Production deployment
netlify deploy --prod
AWS
AWS Lambda
Deploy as Lambda functions:
// vite.config.ts
import { defineConfig } from 'vite'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { nitro } from 'nitro/vite'
export default defineConfig({
plugins: [
tanstackStart(),
nitro({
preset: 'aws-lambda',
}),
],
})
AWS EC2
Deploy to EC2 instances:
- Build the application
- Upload to EC2
- Install dependencies
- Run with PM2:
# Install PM2
npm install -g pm2
# Start application
pm2 start .output/server/index.mjs --name "my-app"
# Save configuration
pm2 save
pm2 startup
Static Hosting
For static-only deployments (no server functions):
Configuration
// vite.config.ts
import { defineConfig } from 'vite'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
export default defineConfig({
plugins: [
tanstackStart({
static: true, // Enable static generation
}),
],
})
Build
Deploy the .output/public directory to:
- Cloudflare Pages
- GitHub Pages
- Amazon S3
- Any static host
Reverse Proxy
Run behind a reverse proxy (nginx):
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Environment Management
Environment Variables
Create environment-specific files:
# .env.development
VITE_API_URL=http://localhost:3000
DATABASE_URL=postgresql://localhost/dev
# .env.production
VITE_API_URL=https://api.example.com
DATABASE_URL=postgresql://prod-server/db
Loading Environment Variables
// Access in server functions
export const getData = createServerFn({ method: 'GET' }).handler(async () => {
const apiKey = process.env.API_KEY
const dbUrl = process.env.DATABASE_URL
// Use environment variables
})
// Access in client code (must be prefixed with VITE_)
const apiUrl = import.meta.env.VITE_API_URL
Caching
Implement caching strategies:
export const Route = createFileRoute('/api/data')({
server: {
handlers: {
GET: async () => {
const data = await fetchData()
return Response.json(data, {
headers: {
'Cache-Control': 'public, max-age=3600, s-maxage=3600',
'CDN-Cache-Control': 'public, max-age=86400',
},
})
},
},
},
})
Compression
Enable compression:
// vite.config.ts
import compression from 'vite-plugin-compression'
export default defineConfig({
plugins: [
tanstackStart(),
compression(),
],
})
Asset Optimization
// vite.config.ts
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
router: ['@tanstack/react-router'],
},
},
},
},
})
Health Checks
Implement health check endpoints:
export const Route = createFileRoute('/api/health')({
server: {
handlers: {
GET: async () => {
// Check database connection
const dbHealthy = await checkDatabase()
// Check external services
const servicesHealthy = await checkServices()
const healthy = dbHealthy && servicesHealthy
return Response.json(
{
status: healthy ? 'ok' : 'error',
timestamp: new Date().toISOString(),
checks: {
database: dbHealthy,
services: servicesHealthy,
},
},
{ status: healthy ? 200 : 503 }
)
},
},
},
})
Monitoring
Error Tracking
Integrate error tracking:
// middleware/error-tracking.ts
import * as Sentry from '@sentry/node'
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
})
export const errorTracking = createMiddleware().server(
async ({ next }) => {
try {
return await next()
} catch (error) {
Sentry.captureException(error)
throw error
}
},
)
Logging
Implement structured logging:
import pino from 'pino'
const logger = pino({
level: process.env.LOG_LEVEL || 'info',
})
export const loggingMiddleware = createMiddleware().server(
async ({ request, next }) => {
const start = Date.now()
logger.info({ url: request.url, method: request.method }, 'Request started')
try {
const result = await next()
logger.info(
{
url: request.url,
method: request.method,
duration: Date.now() - start,
status: result.response.status,
},
'Request completed'
)
return result
} catch (error) {
logger.error(
{ url: request.url, method: request.method, error },
'Request failed'
)
throw error
}
},
)
CI/CD
GitHub Actions
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
API_KEY: ${{ secrets.API_KEY }}
- name: Deploy
run: npm run deploy
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
Best Practices
-
Environment Variables
- Never commit secrets
- Use different values per environment
- Prefix client variables with
VITE_
-
Build Optimization
- Enable compression
- Split vendor bundles
- Optimize images and assets
-
Monitoring
- Set up error tracking
- Implement health checks
- Monitor performance metrics
-
Security
- Use HTTPS in production
- Set security headers
- Implement rate limiting
- Keep dependencies updated
-
Scaling
- Use CDN for static assets
- Implement caching strategies
- Consider serverless for auto-scaling
-
Backup & Recovery
- Automate database backups
- Document recovery procedures
- Test disaster recovery
Troubleshooting
Build Errors
# Clear cache and rebuild
rm -rf .output node_modules
npm install
npm run build
Runtime Errors
Check logs:
# Node.js
node .output/server/index.mjs
# PM2
pm2 logs my-app
# Docker
docker logs container-name
- Enable compression
- Check database query performance
- Review bundle sizes
- Implement caching
Next Steps