cloudflare-api
Hit the Cloudflare REST API directly for operations that wrangler and MCP can't handle well. Bulk DNS, custom hostnames, email routing, cache purge, WAF rules,…
Cloudflare D1 migration workflow: generate with Drizzle, inspect SQL for gotchas, apply to local and remote, fix stuck migrations, handle partial failures. Use when running migrations, fixing migration errors, or setting up D1 schemas.
$ npx -y skills add jezweb/claude-skills --skill d1-migration --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/d1-migrationContext preview
The summary Claude sees to decide when to auto-load this skill.
Cloudflare D1 migration workflow: generate with Drizzle, inspect SQL for gotchas, apply to local and remote, fix stuck migrations, handle partial failures. Use when running migrations, fixing migration errors, or setting up D1 schemas.
name: d1-migration description: "Cloudflare D1 migration workflow: generate with Drizzle, inspect SQL for gotchas, apply to local and remote, fix stuck migrations, handle partial failures. Use when running migrations, fixing migration errors, or setting up D1 schemas." compatibility: claude-code-only
Guided workflow for Cloudflare D1 database migrations using Drizzle ORM.
pnpm db:generate
This creates a new `.sql` file in `drizzle/` (or your configured migrations directory).
**Always read the generated SQL before applying.** Drizzle sometimes generates destructive migrations for simple schema changes.
If you see this pattern, the migration will likely fail:
CREATE TABLE `my_table_new` (...); INSERT INTO `my_table_new` SELECT ..., `new_column`, ... FROM `my_table`; -- ^^^ This column doesn't exist in old table! DROP TABLE `my_table`; ALTER TABLE `my_table_new` RENAME TO `my_table`;
**Cause**: Changing a column's `default` value in Drizzle schema triggers full table recreation. The INSERT SELECT references the new column from the old table.
**Fix**: If you're only adding new columns (no type/constraint changes on existing columns), simplify to:
ALTER TABLE `my_table` ADD COLUMN `new_column` TEXT DEFAULT 'value';
Edit the `.sql` file directly before applying.
pnpm db:migrate:local # or: npx wrangler d1 migrations apply DB_NAME --local
pnpm db:migrate:remote # or: npx wrangler d1 migrations apply DB_NAME --remote
**Always apply to BOTH local and remote before testing.** Local-only migrations cause confusing "works locally, breaks in production" issues.
# Check local npx wrangler d1 execute DB_NAME --local --command "PRAGMA table_info(my_table)" # Check remote npx wrangler d1 execute DB_NAME --remote --command "PRAGMA table_info(my_table)"
When a migration partially applied (e.g. column was added but migration wasn't recorded), wrangler retries it and fails on the duplicate column.
**Symptoms**: `pnpm db:migrate` errors on a migration that looks like it should be done. `PRAGMA table_info` shows the column exists.
# 1. Verify the column/table exists npx wrangler d1 execute DB_NAME --remote \ --command "PRAGMA table_info(my_table)" # 2. Check what migrations are recorded npx wrangler d1 execute DB_NAME --remote \ --command "SELECT * FROM d1_migrations ORDER BY id"
# 3. Manually record the stuck migration
npx wrangler d1 execute DB_NAME --remote \
--command "INSERT INTO d1_migrations (name, applied_at) VALUES ('0013_my_migration.sql', datetime('now'))"
# 4. Run remaining migrations normally
pnpm db:migrateD1's parameter limit causes silent failures with large multi-row INSERTs. Batch into chunks:
const BATCH_SIZE = 10;
for (let i = 0; i < allRows.length; i += BATCH_SIZE) {
const batch = allRows.slice(i, i + BATCH_SIZE);
await db.insert(myTable).values(batch);
}**Why**: D1 fails when rows x columns exceeds ~100-150 parameters.
| Context | Convention | Example | |---------|-----------|---------| | Drizzle schema | camelCase | `caseNumber: text('case_number')` | | Raw SQL queries | snake_case | `UPDATE cases SET case_number = ?` | | API responses | Match SQL aliases | `SELECT case_number FROM cases` |
When creating a D1 database for a new project, follow this order:
1. **Deploy Worker first** — `npm run build && npx wrangler deploy` 2. **Create D1 database** — `npx wrangler d1 create project-name-db` 3. **Copy database_id** to `wrangler.jsonc` `d1_databases` binding 4. **Redeploy** — `npx wrangler deploy` 5. **Run migrations** — apply to both local and remote
Production workflow skills for Claude Code. Each skill guides Claude through a recipe to produce tangible output — scaffolded projects, generated assets, professional documents, deployed services. Ten plugins of practical, production-oriented skills.
Repo: jezweb/claude-skills
Hit the Cloudflare REST API directly for operations that wrangler and MCP can't handle well. Bulk DNS, custom hostnames, email routing, cache purge, WAF rules,…
Scaffold and deploy Cloudflare Workers with Hono routing, Vite plugin, and Static Assets. Describe project, scaffold structure, configure bindings, deploy. Use…
Generate Drizzle ORM schemas for Cloudflare D1 databases with correct D1-specific patterns. Produces schema files, migration commands, type exports, and…
Generate database seed scripts with realistic sample data. Reads Drizzle schemas or SQL migrations, respects foreign key ordering, produces idempotent…
Scaffold Hono API routes for Cloudflare Workers. Produces route files, middleware, typed bindings, Zod validation, error handling, and API_ENDPOINTS.md…
Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind…