Claude-skill-registry alchemy-cloudflare
Alchemy IaC patterns for deploying TanStack Start apps to Cloudflare Workers with D1 databases. Use when setting up new TanStack Start projects, configuring Alchemy deployments, working with D1/Drizzle migrations, local development with Cloudflare bindings, or deploying to custom domains.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/alchemy-cloudflare" ~/.claude/skills/majiayu000-claude-skill-registry-alchemy-cloudflare && rm -rf "$T"
manifest:
skills/data/alchemy-cloudflare/SKILL.mdsafety · automated scan (low risk)
This is a pattern-based risk scan, not a security review. Our crawler flagged:
- references .env files
Always read a skill's source content before installing. Patterns alone don't mean the skill is malicious — but they warrant attention.
source content
Alchemy Cloudflare IaC
TypeScript-first Infrastructure as Code for deploying TanStack Start applications to Cloudflare Workers.
Core Concepts
- alchemy.run.ts: Infrastructure definition file (TypeScript, not YAML)
- TanStackStart resource: Wraps Worker config specifically for TanStack builds
- D1Database resource: Manages D1 with automatic Drizzle migration application
- Type inference:
provides types without codegentypeof worker.Env - Secrets:
encrypts values withalchemy.secret()ALCHEMY_PASSWORD
Quick Start
1. Install Dependencies
pnpm add alchemy @cloudflare/workers-types
2. Create alchemy.run.ts
import alchemy from "alchemy" import { D1Database, TanStackStart } from "alchemy/cloudflare" const app = await alchemy("my-app", { stage: process.env.STAGE ?? "dev", phase: process.argv.includes("--destroy") ? "destroy" : "up", }) const db = await D1Database("my-d1", { migrationsDir: "./drizzle", // Auto-applies Drizzle migrations }) const worker = await TanStackStart("my-worker", { d1Databases: { DB: db }, domains: ["my-app.com"], // Custom domain }) export type Env = typeof worker.Env await app.finalize()
3. Configure Vite
CRITICAL: Alchemy plugin must be FIRST in plugins array.
// app.config.ts import { defineConfig } from "@tanstack/react-start/config" import viteTsConfigPaths from "vite-tsconfig-paths" import { alchemy } from "alchemy/cloudflare/tanstack-start" export default defineConfig({ vite: { plugins: [ alchemy(), // MUST be first viteTsConfigPaths({ root: "./" }), ], build: { target: "esnext", rollupOptions: { external: ["node:async_hooks", "cloudflare:workers"], }, }, }, })
4. Deploy
# Set encryption password (once) export ALCHEMY_PASSWORD="your-secure-password" # Deploy bun alchemy.run.ts # Deploy to specific stage STAGE=prod bun alchemy.run.ts # Destroy resources bun alchemy.run.ts --destroy
Local Development
# Run dev server with Cloudflare emulation pnpm alchemy dev
What this provides:
- Full D1 database emulation (persisted in
).alchemy/{app}/{stage}/ - KV, R2, Durable Objects bindings
- Same
types as productionEnv
Only required env var:
ALCHEMY_PASSWORD=your-password
D1 + Drizzle Integration
Migration Workflow
- Modify schema in
src/db/schema.ts - Generate migration:
pnpm drizzle-kit generate - Deploy:
(auto-applies migrations)bun alchemy.run.ts
Accessing D1
// In server functions or loaders import { getCloudflareContext } from "@opennextjs/cloudflare" export async function loader() { const { env } = await getCloudflareContext() const db = drizzle(env.DB) // Use db... }
Common Patterns
Multiple Environments
const stage = process.env.STAGE ?? "dev" const app = await alchemy("my-app", { stage }) // Conditional resources const domains = stage === "prod" ? ["app.com", "www.app.com"] : [`${stage}.app.com`] await TanStackStart("worker", { domains })
Secrets Management
// In alchemy.run.ts const worker = await TanStackStart("worker", { vars: { PUBLIC_API_URL: "https://api.example.com", }, secretTextBindings: { AUTH_SECRET: alchemy.secret(process.env.AUTH_SECRET!), STRIPE_KEY: alchemy.secret(process.env.STRIPE_KEY!), }, })
KV Namespace
import { KVNamespace, TanStackStart } from "alchemy/cloudflare" const sessions = await KVNamespace("sessions") await TanStackStart("worker", { kvNamespaces: { SESSIONS: sessions }, })
Troubleshooting
"cloudflare:workers" resolve error
Add to vite config:
rollupOptions: { external: ["node:async_hooks", "cloudflare:workers"], }
"Route files should not import @/db"
Server functions must be in
src/server-fns/ files, not inline in route files. Routes can only import and call server functions.
D1 not persisting locally
Check
.alchemy/{app}/{stage}/ directory exists. Ensure ALCHEMY_PASSWORD is set.
Migration not applying
Verify
migrationsDir points to correct directory (where .sql files are).
References
- references/vite-config.md - Complete Vite configuration example
- references/alchemy-run.md - Full alchemy.run.ts example with all resources