TanStack Start applications can deploy to any platform that supports Node.js or WinterCG-compatible runtimes. This template is built specifically for Cloudflare Workers, taking advantage of native bindings for D1, R2, and Workers AI.
Prerequisites
Before deploying, you need:
A Cloudflare account
A D1 database provisioned for your account
An R2 bucket created for asset storage
All project dependencies installed (pnpm install) — the project scripts run the Cloudflare CLI for you
Local Development
Run the dev server locally before deploying:
pnpm dev
This starts the Vite dev server with Miniflare simulating the Workers runtime. D1 and R2 are emulated locally using disk storage.
Set your environment variables in .env (copy from .env.example). .env is the single local source for all configuration values — do not use .env.local or .dev.vars as the primary setup.
Database Setup
The template uses Drizzle ORM with Cloudflare D1. Generate and apply migrations:
pnpm db:generatepnpm db:migrate:local
The migrations create tables for users, sessions, newsletter subscriptions, contact messages, and payment records.
For remote deployment, apply migrations to your production D1 database:
pnpm db:migrate:remote
R2 Storage
User-uploaded assets like profile avatars are stored in R2. The bucket is accessed through a binding defined in cloudflare.config.ts. No API keys or secrets are needed — R2 uses the Worker's identity for authentication.
To set up R2:
Create a bucket in the Cloudflare Dashboard
Add the binding to the env block in cloudflare.config.ts:
Run pnpm deploy:production to provision the binding
Workers AI
The template includes AI tools for summarization, translation, and content generation using Cloudflare Workers AI. Local development uses the REST API with your Cloudflare credentials. Production uses the native AI binding.
The models are configured in cloudflare.config.ts and accessed through src/server/ai/. No separate API keys are required.
Environment Variables
The project uses .env as the single source for all configuration. Run the environment sync tool to push values to Cloudflare:
# Preview what will be synced without making changespnpm cloudflare:sync-env --dry-run# Sync non-sensitive values into the local vars file; secrets ride the next deploypnpm cloudflare:sync-env
This script writes only non-sensitive values (like PAYMENT_PROVIDER or VITE_BASE_URL) into the local cloudflare.vars.json, which cloudflare.config.ts imports. API keys and other secrets never enter any tracked file — they upload with the Worker version during pnpm deploy:production.
Never put secrets into a tracked file. Always use cloudflare:sync-env to keep everything in sync from .env.
Deploying
The project provides a structured deployment pipeline. Start by verifying your configuration:
# Check that .env and tracked values are in sync (refuses to continue if out of sync)pnpm deploy:check# Deploy to productionpnpm deploy:production
deploy:check validates that .env matches the generated cloudflare.vars.json. deploy:production builds and deploys the Worker bundle. Always use these scripts rather than invoking the Cloudflare CLI directly — they ensure secrets, environment variables, and bindings are all aligned.
Post-Deployment
After the first deploy:
Verify your custom domain is routing correctly
Run pnpm db:migrate:remote to apply any pending migrations
Test authentication, payments, and email flows
Set up monitoring in the Cloudflare Dashboard
Your SaaS is now live on Cloudflare Workers, with D1 for data, R2 for assets, and Workers AI for intelligence — all at the edge.