Deploy
Everything you need to set up, configure, and deploy this template to Cloudflare Workers.
Prerequisites
One-time setupBefore you begin, make sure you have Node.js installed and a Cloudflare account. Then install and authenticate the wrangler CLI.
# Install wrangler globally npm install -g wrangler # Authenticate with your Cloudflare account wrangler login
wrangler login opens your browser to authorize the CLI. You only need to do this once per machine.
Project Configuration
wrangler.jsoncThe wrangler.jsonc file is the central config for your Cloudflare project — worker name, compatibility settings, environment variables, and resource bindings.
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "claude-start-cf",
"compatibility_date": "2025-09-24",
"compatibility_flags": ["nodejs_compat"],
"main": "@tanstack/react-start/server-entry",
// Non-secret vars — available via process.env
"vars": {
"APP_ENVIRONMENT": "production",
"DEMO_WRANGLER_VAR": "set-via-wrangler-jsonc"
},
// Resource bindings (D1, R2, KV, etc.)
"d1_databases": [ ... ],
"r2_buckets": [ ... ]
}name — The worker name on Cloudflare (also the default subdomain: name.workers.dev).
compatibility_date — Pins the Workers runtime behavior to a specific date. Update periodically to get new features.
nodejs_compat — Enables Node.js API compatibility in Workers (required by TanStack Start).
D1 Database Setup
wrangler d1 createCreate a D1 database, add the binding to your config, and run migrations.
# Create a new D1 database wrangler d1 create acme-db # Output: # ✅ Successfully created DB 'acme-db' # database_id = "40793ebc-0810-..." # database_name = "acme-db"
Copy the output into your wrangler.jsonc:
"d1_databases": [
{
"binding": "DB",
"database_name": "acme-db",
"database_id": "40793ebc-0810-434d-..."
}
]Run migrations against your remote database:
# Apply migrations to remote D1 wrangler d1 migrations apply acme-db --remote # Or execute SQL directly wrangler d1 execute acme-db --remote --command "SELECT * FROM users"
R2 Bucket Setup
wrangler r2 bucket createCreate an R2 bucket for object storage and add the binding to your config.
# Create a new R2 bucket wrangler r2 bucket create acme-bucket # Output: # ✅ Created bucket 'acme-bucket'
Add the binding to wrangler.jsonc:
"r2_buckets": [
{
"binding": "BUCKET",
"bucket_name": "acme-bucket"
}
]The binding name (BUCKET) is how you access it in code via env.BUCKET in Workers or through the Cloudflare context in server functions.
Secrets & Environment Variables
.dev.vars / wrangler secretThree ways to set environment variables: wrangler.jsonc vars for non-secrets, wrangler secret for production secrets, and .dev.vars for local development.
Non-secret vars (committed to repo)
// wrangler.jsonc
"vars": {
"APP_ENVIRONMENT": "production",
"PUBLIC_API_URL": "https://api.example.com"
}Production secrets (encrypted, never in repo)
# Set a secret for production wrangler secret put API_KEY # Enter value when prompted # List all secrets wrangler secret list
Local development secrets
# .dev.vars (gitignored) API_KEY=sk-local-dev-key-here DATABASE_URL=http://localhost:8787
VITE_ prefix: Variables prefixed with VITE_ are exposed to client-side code. Never use this prefix for secrets.
Deployment
npm run deployDeploy your app to Cloudflare Workers with a single command. Under the hood it builds with Vite then uploads via wrangler.
# Build and deploy to production npm run deploy # What this runs: # 1. npm run build → vite build && tsc --noEmit # 2. wrangler deploy → uploads worker + assets to Cloudflare
Build step — Vite bundles your app (SSR + client), TanStack Start generates the server entry, and TypeScript checks types.
Deploy step — Wrangler uploads the worker bundle and static assets to Cloudflare's edge network. Your app is live at name.workers.dev (or your custom domain).
First deploy? Make sure you've created your D1 database and R2 bucket first, and that the IDs in wrangler.jsonc match.
Local Development
npm run devRun your app locally with Miniflare — a local Cloudflare Workers simulator that provides D1, R2, and other bindings without deploying.
# Start local dev server npm run dev # Runs Vite dev server with Cloudflare plugin # → Local D1 database (SQLite file in .wrangler/) # → Local R2 bucket (files in .wrangler/) # → Hot module replacement # → Server functions with Workers runtime
Local secrets are loaded from .dev.vars in your project root. This file is gitignored by default.
Tip: Run npm run cf-typegen after changing wrangler.jsonc to regenerate TypeScript types for your bindings.