cloudflare-workers-author
Skill17 starsChanged 56 days agoMITView on GitHub
Workflow for building production-grade Cloudflare Workers in TypeScript - bootstrap, bindings and storage choice, routing (Hono + RPC via WorkerEntrypoint), testing with @cloudflare/vitest-plugin, gradual deployments, and common pitfalls. Use when adding a new Worker, adding endpoints to an existing Worker, choosing between KV / R2 / D1 / Durable Objects / Hyperdrive, setting up testing, configuring deployment, or reviewing a Worker PR.
In this repository53 other files it gives its agents.
- agents-sdkSkill
- agent-workflowSkill
- api-designSkill
- aws-iamSkill
- bash-shell-scriptingSkill
- cicd-github-actionsSkill
- cloudflare-email-serviceSkill
- cloudflareSkill
- cloudflare-waf-authorSkill
- cloud-platformsSkill
- codebase-security-auditSkill
- containers-orchestrationSkill
- core-engineeringSkill
- database-postgresqlSkill
- databricksSkill
- data-engineeringSkill
- distributed-transactionsSkill
- documentation-standardsSkill
- domain-driven-designSkill
- durable-objectsSkill
- frontend-engineeringSkill
- git-workflowSkill
- go-rust-systemsSkill
- iam-security-advisorSkill
- independent-verificationSkill
- infrastructure-iacSkill
- kubernetes-containersSkill
- kubernetes-operator-developmentSkill
- mcp-developmentSkill
- memory-architectureSkill
- multi-perspective-reviewSkill
- networking-transportSkill
- observabilitySkill
- oktaSkill
- pdf-exportSkill
- python-developmentSkill
- reactflow-architecture-diagramsSkill
- sandbox-sdkSkill
- scripting-automationSkill
- security-testingSkill
- service-resilienceSkill
- single-file-dashboardSkill
- skills-compositionSkill
- skills-continuous-improvementSkill
- snowflakeSkill
- system-designSkill
- typescript-javascriptSkill
- web-perfSkill
- web-research-kb-refreshSkill
- workers-best-practicesSkill
- workload-identitySkill
- wranglerSkill
- zero-trustSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 2 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 25
Do NOT invoke for:
- Very specific: line 54
If this is a new Worker (no existing wrangler.jsonc), follow references/project-bootstrap.md to get a minimal Module Workers project with:
- Very specific: line 65
If the user already has a Worker, read their existing wrangler.jsonc before suggesting changes.
- Distinctive: line 82
Document the choice in the PR description with the rejected alternatives and why.
- Very specific: line 105
Unit tests: import the handler, call worker.fetch(request, env, ctx) directly with mocked env
- Very specific: line 106
Integration tests: use SELF.fetch() from cloudflare:test (in-process) or auxiliary Workers (fresh isolate)
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Cloudflare Workers Author
Companion rule: 401-cloudflare-workers.mdc (file-scoped to wrangler.{jsonc,toml,json} and common Worker entry-point names). The rule is the gate (non-negotiables); this skill is the workflow (how to actually build the Worker).
Voice: opinionated. Cloudflare Workers is a small, fast platform with a specific runtime model. Most production incidents come from treating it like a generic Node.js server (top-level await, mutable module state, unbounded loops, secrets in logs, public-URL Worker-to-Worker calls). The workflow below prevents those.
When to invoke this skill
Invoke when:
- The user asks to build a new Cloudflare Worker, Durable Object, Workflow, Queue consumer, Cron Trigger, Email Worker, or Pages Function.
- The user is adding routes / endpoints to an existing Worker.
- The user asks "should I use KV / D1 / R2 / DO / Hyperdrive for this?" (the bindings-and-storage decision matrix is the answer).
- The user is setting up testing for a Worker.
- The user is configuring deployment (gradual rollouts, OIDC for GitHub Actions, secret rotation).
- A PR review touches
wrangler.jsonc, a Worker entry-point file, or a binding configuration.
Do NOT invoke for:
- Cloudflare Pages static-site work (not Worker authoring). See
cloud-platforms/references/cloudflare.md§ Pages. - WAF rule authoring (use
cloudflare-waf-authorskill instead). - Generic JavaScript / TypeScript code that happens to be imported by a Worker - delegate to the
typescript-javascriptskill.
Pre-step: classify what you're building
Each Worker type has a different entry-point shape and different bindings emphasis. Ask the user which one if unclear - the wrong entry-point shape is a wrong-handler-signature bug that won't surface until deploy time.
| Type | Entry point | Most common bindings |
| Default-export HTTP Worker | export default { async fetch(req, env, ctx) {...} } satisfies ExportedHandler<Env> | KV, D1, R2, AI, Service Bindings |
| Named-entrypoint (RPC target) | export default class extends WorkerEntrypoint { async myMethod() {...} } | Same, called via Service Binding from another Worker |
| Durable Object | export class Room extends DurableObject {...} + a default fetch handler that routes to DO | DO storage + KV / R2 for cold data |
| Workflow | export class MyWorkflow extends WorkflowEntrypoint { async run(event, step) {...} } | KV, D1, R2, Service Bindings, AI |
| Queue consumer | export default { async queue(batch, env, ctx) {...} } | D1, R2, Service Bindings, AI |
| Cron Trigger | export default { async scheduled(event, env, ctx) {...} } | KV, D1, R2, Service Bindings |
| Email Worker | export default { async email(message, env, ctx) {...} } | R2 for attachments, D1 for logs |
| Pages Function | export const onRequest: PagesFunction<Env> = async (ctx) => {...} (in functions/[[path]].ts) | KV, D1, R2 (subset of full Worker bindings) |
The six-step workflow
Step 1 - Bootstrap the project
If this is a new Worker (no existing wrangler.jsonc), follow references/project-bootstrap.md to get a minimal Module Workers project with:
wrangler.jsonc(the modern config format - JSONC with comments; recommended by Cloudflare since Wrangler v3.91.0)package.jsonwithwrangler,typescript, and atypesscript that runswrangler typestsconfig.jsonwith strict mode, ESNext target,"types": [], and the generatedworker-configuration.d.tsinincludesrc/worker.tswith the generatedEnvtype (do not hand-author it) andsatisfies ExportedHandler<Env>.dev.varsin.gitignore;worker-configuration.d.tsgenerated bywrangler types
[!IMPORTANT]
wrangler typesnow generates the Workers runtime types and supersedes@cloudflare/workers-types. Current Wrangler (4.9x+) prints this on everywrangler typesrun and tells you to uninstall@cloudflare/workers-typesand remove it fromtsconfig.json. The generatedworker-configuration.d.tsprovides both the globalEnv(fromvars+ declaredsecrets) and the runtime globals (Request,Response,ExecutionContext,ExportedHandler, etc.), pinned to yourcompatibility_date. So: no@cloudflare/workers-typesdependency,"types": []intsconfig.json, andworker-configuration.d.tsininclude. Declare expected secrets undersecrets.requiredinwrangler.jsoncso they appear in the generatedEnv. Vars are typed as their literal values by default; runwrangler types --strict-vars=falseto type them asstringwhen a var's value varies by environment.
If the user already has a Worker, read their existing wrangler.jsonc before suggesting changes. Don't propose a fresh structure that conflicts with their conventions.
Step 2 - Choose bindings and storage
This is the most consequential design decision in any new Worker. Pick wrong and you'll be migrating data in six months. The full decision matrix is in references/bindings-and-storage.md; the headline:
| Need | Use | Don't use |
| Session / config / feature flag (small, eventually consistent, low write) | KV | D1, R2 |
| Relational queries, transactions, joins (single-region, SQLite scale) | D1 | KV |
| File / blob storage (any size; metadata + body) | R2 | KV (25 MB value limit) |
| Strongly-consistent coordination (sessions, rate limits, websocket fan-out) | Durable Object | KV (eventually consistent), D1 (single-region, not strongly consistent across Workers) |
| Connection pooling to existing Postgres / MySQL | Hyperdrive | Direct TCP (works but no pooling) |
| Job queues, dead-letter, batching | Queues | Manual KV-based queue |
| LLM inference | Workers AI behind AI Gateway (cost cap + caching + observability) | Direct provider API calls |
| Vector search | Vectorize | KV with embedding lookups (no ANN index) |
Document the choice in the PR description with the rejected alternatives and why.
Step 3 - Route requests
Pick a router based on complexity:
| Complexity | Choice | Why |
| 1-3 routes, no middleware | Native URL + switch | Zero deps, smallest bundle |
| Many routes, middleware, typed env | Hono (de facto) | Typed, fast, designed for edge runtimes, OpenAPI integration available |
| Worker-to-Worker calls only | RPC via WorkerEntrypoint | No HTTP overhead, typed arguments and return values, faster than HTTP service bindings |
| GraphQL | GraphQL Yoga + Hono | Yoga has a Workers adapter |
For Hono patterns (typed env via Hono<{ Bindings: Env, Variables: ... }>, middleware, error boundaries, OpenAPI) and RPC patterns (when to use, named entrypoints, lifecycle), see references/hono-patterns.md.
Step 4 - Test
The canonical testing path is @cloudflare/vitest-plugin v1+ with Vitest 4.1+. It runs tests inside the Workers runtime via Miniflare, with bindings mocked or real (your choice), HMR for fast reruns, and isolated per-test storage.
See references/testing-with-vitest-pool.md for setup details. The pattern:
vitest.config.tsregisters thecloudflareTest()Vite plugin (exported from@cloudflare/vitest-plugin) inside a standarddefineConfigfromvitest/config, pointing at yourwrangler.jsonctsconfig.jsonfor tests includes"@cloudflare/vitest-plugin/types"intypes(declares thecloudflare:testmodule)- Unit tests: import the handler, call
worker.fetch(request, env, ctx)directly with mocked env - Integration tests: use
SELF.fetch()fromcloudflare:test(in-process) or auxiliary Workers (fresh isolate)
[!IMPORTANT] Cloudflare renamed
@cloudflare/vitest-pool-workersto@cloudflare/vitest-pluginin v1. Migrate the dependency, package imports, and TypeScripttypesentry. The configuration API remainscloudflareTest({ wrangler: { configPath: "./wrangler.jsonc" } })insidepluginsin avitest/configdefineConfig; do not restore the removeddefineWorkersConfighelper.
Reject in review: new tests using unstable_dev or the renamed @cloudflare/vitest-pool-workers package.
Step 5 - Deploy and roll out gradually
Workers supports two deployment models:
- Standard deploy (
wrangler deploy) - upload and immediately serve 100% from the new version. Fine for low-risk changes. - Gradual deployment (
wrangler versions uploadthenwrangler versions deploy) - upload as a new version without serving traffic, split traffic between old and new, then promote to 100%. Required for production HTTP Workers serving customer traffic.
Headline commands:
# Upload new version without deploying
wrangler versions upload
# Interactive split (prompts for percentages)
wrangler versions deploy
# Non-interactive: 90% old, 10% new
wrangler versions deploy <old-version-id>@90 <new-version-id>@10
# Promote to 100%
wrangler versions deploy <new-version-id>@100Smoke-test a specific version in production via the Cloudflare-Workers-Version-Overrides request header (the version override applies even when its percentage is 0%).
For CI integration (OIDC trust for GitHub Actions instead of long-lived API tokens), secret rotation, and the canary-then-promote pattern, see references/deployment-and-versions.md.
Step 6 - Verify and ship
Before merge:
wrangler typesregenerated;worker-configuration.d.tsmatcheswrangler.jsonctsc --noEmitcleanwrangler deploy --dry-runclean (catches binding misconfigurations)@cloudflare/vitest-plugintests pass- PR description names the rejected storage alternatives and why
- PR description names the soak plan for the gradual rollout (e.g., "10% for 1h, then 50% for 1h, then 100%")
- Reviewer checklist from
401-cloudflare-workers.mdcticked
Self-check before submitting
The high-leverage subset of the 401-cloudflare-workers.mdc reviewer checklist:
- Module Workers syntax (
export default {...}orclass extends WorkerEntrypoint); noaddEventListener("fetch", ...) Envinterface imported from generatedworker-configuration.d.ts;satisfies ExportedHandler<Env>on the default export- No secrets in
console.log, error messages, response bodies, or thrown errors - All fire-and-forget async work wrapped in
ctx.waitUntil() - Cloudflare resources declared as bindings (not env vars); Worker-to-Worker calls use Service Bindings + RPC (not public URLs)
- Subrequest budget considered; loops use batching where the API supports it (D1
batch(), etc.) - No top-level await, no module-scope mutable state, no module-scope
fetch() compatibility_dateset;compatibility_flagsminimal and justifiedwrangler.jsoncis source of truth; deployment from CI (not Dashboard "Edit code")- Tests use
@cloudflare/vitest-plugin(not deprecatedunstable_dev)
See references/common-pitfalls.md for the full list of failure modes observed across many Workers teams, organized by symptom (cold-start regressions, intermittent state pollution, secret leaks, subrequest budget exhaustion, deployment drift).
Related
401-cloudflare-workers.mdc- the rule (file-scoped non-negotiables)400-cloudflare.mdc- broader Cloudflare platform playbook405-cloudflare-waf-rules.mdc- file-scoped WAF rule playbookcloud-platformsskill - cross-cloud platform patternscloudflare-waf-authorskill - WAF rule authoring workflow companionskills/typescript-javascript- general TypeScript / JavaScript patterns
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

