claude-start-cf

Deploy

Everything you need to set up, configure, and deploy this template to Cloudflare Workers.

Prerequisites

One-time setup

Before 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.jsonc

The 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 create

Create 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 create

Create 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 secret

Three 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 deploy

Deploy 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 dev

Run 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.