Skip to content
Back to skills

1357 Deployment 28c3c43e

ASecurity

Production deployment checklist and common mistakes for TanStack Start on Cloudflare Workers.

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
developmenttypescriptrustgobashreactnodenodejstestinggitapi

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 1357-deployment_28c3c43e --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 1357 Deployment 28c3c43e?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 1357 Deployment 28c3c43e
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-1357-deployment-28c3c43e/badge)](https://www.skillsdirectory.com/skills/tools-only-1357-deployment-28c3c43e)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Deployment Reference

Production deployment checklist and common mistakes for TanStack Start on Cloudflare Workers.

## Pre-Deploy Checklist

- [ ] `wrangler.jsonc` has correct `account_id`
- [ ] D1 database created and `database_id` in wrangler.jsonc
- [ ] `main` field is `"@tanstack/react-start/server-entry"`
- [ ] `nodejs_compat` in `compatibility_flags`
- [ ] `.dev.vars` is in `.gitignore`
- [ ] No hardcoded secrets in source code

## Deploy Sequence

### 1. Set Production Secrets

```bash
# Generate a DIFFERENT secret than dev
openssl rand -hex 32 | npx wrangler secret put BETTER_AUTH_SECRET

# Use your actual Worker URL (update after first deploy if needed)
echo "https://PROJECT_NAME.SUBDOMAIN.workers.dev" | npx wrangler secret put BETTER_AUTH_URL

# Include all valid origins
echo "http://localhost:3000,https://PROJECT_NAME.SUBDOMAIN.workers.dev" | npx wrangler secret put TRUSTED_ORIGINS
```

### 2. Google OAuth (if using)

```bash
echo "your-client-id" | npx wrangler secret put GOOGLE_CLIENT_ID
echo "your-client-secret" | npx wrangler secret put GOOGLE_CLIENT_SECRET
```

Add production redirect URI in Google Cloud Console:
```
https://PROJECT_NAME.SUBDOMAIN.workers.dev/api/auth/callback/google
```

### 3. Migrate Remote Database

```bash
pnpm db:migrate:remote
```

**Always run migrations on BOTH local AND remote** before testing.

### 4. Build and Deploy

```bash
pnpm build && npx wrangler deploy
```

### 5. Post-Deploy Verification

- [ ] App loads at production URL
- [ ] Auth login/register works
- [ ] Database operations work (create, read, update, delete)
- [ ] Theme persists across page loads
- [ ] No console errors

## Custom Domain (Optional)

After initial deploy:

1. Add custom domain in Cloudflare Dashboard → Workers → your worker → Triggers → Custom Domains
2. Update secrets:
   ```bash
   echo "https://yourdomain.com" | npx wrangler secret put BETTER_AUTH_URL
   echo "http://localhost:3000,https://yourdomain.com" | npx wrangler secret put TRUSTED_ORIGINS
   ```
3. Update Google OAuth redirect URI to use custom domain
4. Redeploy: `npx wrangler deploy`

## Common Mistakes

### 1. TRUSTED_ORIGINS Not Set

**Symptom**: User signs in but gets silently redirected to homepage. Auth cookie not accepted.

**Fix**: Set the TRUSTED_ORIGINS secret with ALL valid URLs (comma-separated, no spaces):
```bash
echo "http://localhost:3000,https://your-app.workers.dev" | npx wrangler secret put TRUSTED_ORIGINS
```

### 2. BETTER_AUTH_URL Mismatch

**Symptom**: Auth works locally but fails in production. Redirect loops or "invalid callback" errors.

**Fix**: The URL must match the actual production URL exactly — including `https://`, no trailing slash. After first deploy, check the actual Worker URL and update:
```bash
echo "https://actual-url.workers.dev" | npx wrangler secret put BETTER_AUTH_URL
npx wrangler deploy  # Must redeploy after setting secret
```

### 3. Secrets Set But Not Deployed

**Symptom**: Changed a secret but the app still uses the old value.

**Fix**: `wrangler secret put` does NOT automatically redeploy. Always run `npx wrangler deploy` after setting secrets.

### 4. Database Migrations Not Applied to Remote

**Symptom**: API returns 500 errors. "Table not found" or "no such table" in logs.

**Fix**: Run migrations on remote:
```bash
pnpm db:migrate:remote
```

### 5. Google OAuth Redirect URI Missing

**Symptom**: "Error 400: redirect_uri_mismatch" when signing in with Google.

**Fix**: Add your production URL to Google Cloud Console → APIs & Services → Credentials → your OAuth client → Authorised redirect URIs:
```
https://your-app.workers.dev/api/auth/callback/google
```

### 6. Wrong Vite Plugin Order

**Symptom**: Build fails or SSR doesn't work. Cryptic Vite errors about "environment not found".

**Fix**: Plugin order in `vite.config.ts` must be: `cloudflare()` → `tailwindcss()` → `tanstackStart()` → `viteReact()`. Cloudflare MUST be first.

### 7. Module-Level Env Access

**Symptom**: `env` is undefined, or "Cannot access env outside of request context".

**Fix**: Never import and use `env` from `cloudflare:workers` at module level. Always access inside server function handlers, route loaders, or API route handlers.

```typescript
// ❌ Module level — fails
import { env } from "cloudflare:workers";
const db = drizzle(env.DB);

// ✅ Inside handler — works
export const getItems = createServerFn({ method: "GET" }).handler(async () => {
  const db = drizzle(env.DB); // env accessed during request
});
```

### 8. Auth on Server Function Instead of API Route

**Symptom**: better-auth endpoints return 404 or auth flow doesn't work.

**Fix**: better-auth needs a catch-all API route (`createAPIFileRoute`), not a server function. It handles its own routing internally:

```typescript
// src/routes/api/auth/$.ts
import { createAPIFileRoute } from "@tanstack/react-start/api";

export const APIRoute = createAPIFileRoute("/api/auth/$")({
  GET: ({ request }) => getAuth().handler(request),
  POST: ({ request }) => getAuth().handler(request),
});
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.