This skill should be used when the user asks about "Workers API", "fetch handler", "Workers runtime", "request handling", "response handling", "Workers bindings", "environment variables in Workers", "Workers context", or discusses implementing Workers code, routing patterns, or using Cloudflare bindings like KV, D1, R2, Durable Objects in Workers.
/plugin marketplace add involvex/involvex-claude-marketplace/plugin install cloudflare-expert@involvex-claude-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
examples/error-handling.jsexamples/fetch-handler-patterns.jsreferences/bindings-guide.mdreferences/runtime-apis.mdThis skill provides comprehensive guidance for developing Cloudflare Workers, including runtime APIs, fetch event handlers, request/response handling, bindings usage, and common development patterns. Use this skill when implementing Workers code, designing Workers architecture, or working with the Workers runtime environment.
Cloudflare Workers run on the V8 JavaScript engine at the edge. Workers use the Service Worker API with extensions specific to the Cloudflare platform.
Workers execute on incoming requests:
The fetch event handler is the entry point for Workers:
export default {
async fetch(request, env, ctx) {
// request: Request object
// env: Bindings and environment variables
// ctx: Execution context with waitUntil() and passThroughOnException()
return new Response('Hello World');
}
};
request: Incoming Request object (Web API standard)
request.url - Full URL stringrequest.method - HTTP method (GET, POST, etc.)request.headers - Headers objectrequest.body - ReadableStream of request bodyrequest.cf - Cloudflare-specific propertiesenv: Environment object containing bindings
env.MY_KVenv.MY_DBenv.MY_BUCKETenv.MY_DOenv.MY_SECRETenv.MY_VARctx: Execution context
ctx.waitUntil(promise) - Extend execution lifetime for async tasksctx.passThroughOnException() - Pass request to origin if Worker throwsMust return a Response object or a Promise that resolves to a Response:
// Direct return
return new Response('Hello', { status: 200 });
// Async return
return await fetch('https://api.example.com');
// With headers
return new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: {
'Content-Type': 'application/json'
}
});
Common routing patterns for multi-route Workers:
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
// Path-based routing
if (url.pathname === '/api/users') {
return handleUsers(request, env);
}
if (url.pathname.startsWith('/api/')) {
return handleAPI(request, env);
}
// Method-based routing
if (request.method === 'POST') {
return handlePost(request, env);
}
// Default
return new Response('Not Found', { status: 404 });
}
};
See examples/fetch-handler-patterns.js for complete routing examples.
Access request properties:
const url = new URL(request.url);
const method = request.method;
const headers = request.headers.get('Authorization');
const cookies = request.headers.get('Cookie');
// Cloudflare-specific properties
const country = request.cf?.country;
const colo = request.cf?.colo; // Data center code
Parse request bodies based on content type:
// JSON
const data = await request.json();
// Form data
const formData = await request.formData();
const field = formData.get('fieldName');
// Text
const text = await request.text();
// Array buffer
const buffer = await request.arrayBuffer();
// Text response
return new Response('Hello World');
// JSON response
return new Response(JSON.stringify({ message: 'Success' }), {
headers: { 'Content-Type': 'application/json' }
});
// HTML response
return new Response('<h1>Hello</h1>', {
headers: { 'Content-Type': 'text/html' }
});
// Status codes
return new Response('Not Found', { status: 404 });
return new Response('Created', { status: 201 });
// Set headers
const headers = new Headers({
'Content-Type': 'application/json',
'Cache-Control': 'max-age=3600',
'X-Custom-Header': 'value'
});
return new Response(body, { headers });
// CORS headers
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type'
};
// 301 permanent redirect
return Response.redirect('https://example.com', 301);
// 302 temporary redirect
return Response.redirect('https://example.com', 302);
Bindings provide access to Cloudflare resources and are configured in wrangler.toml or wrangler.jsonc.
See references/bindings-guide.md for complete binding configuration and usage patterns.
KV (Key-Value):
// Read
const value = await env.MY_KV.get('key');
const json = await env.MY_KV.get('key', 'json');
// Write
await env.MY_KV.put('key', 'value');
await env.MY_KV.put('key', JSON.stringify(data), {
expirationTtl: 3600 // Expire in 1 hour
});
D1 (Database):
// Query
const result = await env.MY_DB.prepare(
'SELECT * FROM users WHERE id = ?'
).bind(userId).first();
// Insert
await env.MY_DB.prepare(
'INSERT INTO users (name, email) VALUES (?, ?)'
).bind(name, email).run();
R2 (Object Storage):
// Read
const object = await env.MY_BUCKET.get('file.txt');
const text = await object.text();
// Write
await env.MY_BUCKET.put('file.txt', 'content');
export default {
async fetch(request, env, ctx) {
try {
// Your logic here
const result = await processRequest(request, env);
return new Response(JSON.stringify(result), {
headers: { 'Content-Type': 'application/json' }
});
} catch (error) {
console.error('Error:', error);
return new Response(JSON.stringify({
error: error.message
}), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
}
};
function errorResponse(message, status = 500) {
return new Response(JSON.stringify({ error: message }), {
status,
headers: { 'Content-Type': 'application/json' }
});
}
// Usage
if (!apiKey) {
return errorResponse('API key required', 401);
}
See examples/error-handling.js for comprehensive error handling patterns.
Use ctx.waitUntil() to perform background tasks that extend beyond the response:
export default {
async fetch(request, env, ctx) {
// Respond immediately
const response = new Response('Request received');
// Continue processing in background
ctx.waitUntil(
logRequest(request, env)
);
return response;
}
};
async function logRequest(request, env) {
await env.MY_DB.prepare(
'INSERT INTO logs (url, timestamp) VALUES (?, ?)'
).bind(request.url, Date.now()).run();
}
Important: waitUntil extends execution but doesn't guarantee completion. Use for non-critical tasks like logging, analytics, or cache warming.
Promise.all() for concurrent operationsconsole.log() for debugging (visible in wrangler tail)wrangler dev before deployingwrangler tail to see production logsenv, not globalsWorkers support standard Web APIs and Cloudflare-specific extensions.
See references/runtime-apis.md for complete API documentation and examples.
Workers fully support TypeScript with official type definitions:
export interface Env {
MY_KV: KVNamespace;
MY_DB: D1Database;
MY_BUCKET: R2Bucket;
MY_SECRET: string;
}
export default {
async fetch(
request: Request,
env: Env,
ctx: ExecutionContext
): Promise<Response> {
// Type-safe access to bindings
const value = await env.MY_KV.get('key');
return new Response(value);
}
};
Install types: npm install -D @cloudflare/workers-types
For detailed information, consult:
references/runtime-apis.md - Complete Workers runtime API documentation with examplesreferences/bindings-guide.md - All binding types with configuration and usage patternsWorking examples in examples/:
fetch-handler-patterns.js - Common routing and request handling patternserror-handling.js - Comprehensive error handling strategiesFor the latest documentation:
Use the cloudflare-docs-specialist agent to search documentation and fetch the latest information.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.