agents/skills/cf-durable-object-package/SKILL.md
Add or change a Durable Object worker package under durable-objects/ (Alchemy, env.d.ts, Hono on the DO). Use when scaffolding with turbo gen durable-object, editing durable-objects/*/alchemy.run.ts, workers/app.ts, or env.d.ts for a DO. Not for web app bindings or cross-worker rpc—see cf-web-alchemy-bindings and cf-worker-rpc-turbo.
npx skillsauth add firtoz/cf-multiworker-boilerplate cf-durable-object-packageInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
durable-objects/<name>/ (generator or copy an example).DurableObjectNamespace, Worker, entrypoint, or the DO’s Hono app.Package layout
Minimum files: alchemy.run.ts, env.d.ts, workers/app.ts, package.json (exports: "./alchemy": "./alchemy.run.ts"), tsconfig.json.
Examples: ping-do (Hono + DO + WorkerEntrypoint), chatroom-do (Socka + DO SQLite + chat-contract).
For WebSocket RPC + server push, prefer Socka + contract over ad hoc WebSocket JSON — cf-socka-realtime.
alchemy.run.ts
await alchemy(…) string must match alchemy-cli / package.json → alchemy.app (${PRODUCT_PREFIX}-<suffix> from ALCHEMY_APP_IDS → alchemy-utils/worker-peer-scripts).requireAlchemyPassword(app) from alchemy-utils.DurableObjectNamespace<YourDoRpc> (types from ./workers/rpc).Worker(...): use DEFAULT_WORKER_RESOURCE_ID (worker); omit name: unless you need an override. Cyclic WorkerRef pairs: omitDefaultPhysicalWorkerScriptName (cf-worker-rpc-turbo).SQLite / Drizzle (persisted DO state)
src/schema.ts.drizzle.config.ts: dialect: "sqlite", driver: "durable-sqlite", schema → that file.package.json: "db:generate": "drizzle-kit generate"; run it → drizzle/*.sql, drizzle/meta/*.json, drizzle/migrations.js.drizzle/sql.d.ts: declare module "*.sql"; tsconfig includes drizzle/**/*.d.ts for SQL imports.env.d.ts — export type CloudflareEnv = (typeof <yourExportedWorker>)["Env"]. declare global { type Env = CloudflareEnv } and declare module "cloudflare:workers" Env merge (match ping-do/env.d.ts).
Hono — In workers/app.ts: import type { CloudflareEnv } from "../env", const app = new Hono<{ Bindings: CloudflareEnv }>() (same as other-worker/workers/app.ts).
Scripts
alchemy in package.json: "alchemy": { "app": "<ALCHEMY_APP_IDS key>", "entry": "alchemy.run.ts" } (omit entry when it is alchemy.run.ts).dev / deploy:* / destroy:*: alchemy-cli --stage local|staging|prod|preview <dev|deploy|destroy> — alchemy-cli loads repo-root dotfiles, sets STAGE, and passes --app from alchemy.app."alchemy-utils": "workspace:*" so alchemy-cli is on script PATH.state-hub: workspace:* devDependency so Turbo ^deploy:* runs the shared remote Alchemy state hub first.db:generate.After edits — From repo root: bun run typegen and bun run typecheck (or package-local typecheck). If schema changed, run package-local db:generate first.
workers/rpc.ts, WorkerRef, root dev / destroy:*: cf-worker-rpc-turbo.If this new DO should be reachable from the web app, complete these follow-up edits:
Root package.json dev: add --filter=<your-package>.
Root turbo.json: add <your-package>#destroy:prod, #destroy:staging, and #destroy:preview depending on the matching @internal/web#destroy:*.
apps/web/package.json: add "<your-package>": "workspace:*" and run bun install.
apps/web/alchemy.run.ts: import from "<your-package>/alchemy" and bind the namespace/worker into ReactRouter.
WebSocket / Socka
apps/web/workers/app.ts: upgrades before React Router; same URL prefix as client; skip Vite HMR; forward to DO /websocket.@firtoz/socka: cf-socka-realtime/SKILL.md — contract, SockaWebSocketDO, useSockaSession, SSR-safe wss://.Verify from repo root: bun run typegen, bun run typecheck, bun run lint.
development
Repo-root commands, typegen and typecheck cadence, lint, deploy, adding packages with bun, and Alchemy app layout. Use at the start of a task, before PR, or when choosing turbo/typegen commands.
development
Fork and template gotchas (env import, routes, typegen, forms, D1, Turbo, HMR, new DO packages). Use when working on apps/web or durable-objects, or when behavior diverges from this stack’s conventions.
testing
Turborepo task configuration patterns for monorepo management. Use when configuring turbo.json tasks, setting up task dependencies, managing cache inputs/outputs, or working with cross-package dependencies in the monorepo.
development
React Router v7 routing patterns and environment variable configuration. Use whenever you touch React Router–related code (routes, links, params, loaders, actions, route config, or env in route context).