Cloudflare Workers — SKILL.md

Raw skill file that agents receive when using this skill

Download
---
name: "Cloudflare Workers"
description: "Skill for Cloudflare Workers — auto-generated from documentation"
version: "1.0.0"
author: "skynet"
category: "infrastructure"
agents: ["claude-code", "codex", "gemini"]
tags: ["cloudflare-workers", "infrastructure", "auto-generated"]
---

# Cloudflare Workers

---
name: Cloudflare Workers
description: Use this skill when building serverless applications, API endpoints, edge computing functions, or middleware that runs on Cloudflare's global network. Perfect for request routing, authentication, caching, A/B testing, and transforming HTTP requests/responses at the edge.
metadata:
  author: skynet
  version: 1.0.0
  category: infrastructure
---

# Cloudflare Workers

## Setup and Authentication

### Install Wrangler CLI
```bash
npm install -g wrangler
# or
npm install wrangler --save-dev
```

### Authentication
```bash
# Login to Cloudflare
wrangler login

# Or use API token
wrangler config set cloudflare_api_token YOUR_API_TOKEN

# Verify authentication
wrangler whoami
```

## Project Initialization

### Create New Worker
```bash
# Create from template
wrangler generate my-worker

# Create from specific template
wrangler generate my-api worker-typescript
wrangler generate my-router worker-router

# Initialize in existing directory
wrangler init my-project
wrangler init my-project --type="webpack"
```

### Basic Worker Structure
```javascript
// src/index.js
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    
    if (url.pathname === '/api/hello') {
      return new Response('Hello World!', {
        headers: { 'Content-Type': 'text/plain' }
      });
    }
    
    return new Response('Not found', { status: 404 });
  },
};
```

## Development Workflow

### Local Development
```bash
# Start dev server
wrangler dev

# Dev with specific port
wrangler dev --port 8080

# Dev with live reload
wrangler dev --live-reload

# Dev with specific compatibility date
wrangler dev --compatibility-date 2023-10-01
```

### Configuration (wrangler.toml)
```toml
name = "my-worker"
main = "src/index.js"
compatibility_date = "2023-10-01"

[env.production]
name = "my-worker-prod"
vars = { ENVIRONMENT = "production" }

[env.staging]
name = "my-worker-staging"
vars = { ENVIRONMENT = "staging" }

[[kv_namespaces]]
binding = "MY_KV"
id = "your-kv-namespace-id"
preview_id = "your-preview-kv-id"
```

## Deployment and Publishing

### Deploy Worker
```bash
# Deploy to production
wrangler publish

# Deploy to specific environment
wrangler publish --env staging
wrangler publish --env production

# Deploy with compatibility flags
wrangler publish --compatibility-flags nodejs_compat
```

### Manage Versions
```bash
# List deployments
wrangler deployments list

# Rollback to previous version
wrangler rollback --message "Rolling back due to issues"

# View deployment details
wrangler deployments view DEPLOYMENT_ID
```

## Common Worker Patterns

### API Route Handler
```javascript
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const path = url.pathname;
    const method = request.method;
    
    // CORS headers
    const corsHeaders = {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE',
      'Access-Control-Allow-Headers': 'Content-Type',
    };
    
    if (method === 'OPTIONS') {
      return new Response(null, { headers: corsHeaders });
    }
    
    try {
      if (path === '/api/users' && method === 'GET') {
        return handleGetUsers(env);
      } else if (path === '/api/users' && method === 'POST') {
        return handleCreateUser(request, env);
      }
      
      return new Response('Not found', { status: 404 });
    } catch (error) {
      return new Response(JSON.stringify({ error: error.message }), {
        status: 500,
        headers: { 'Content-Type': 'application/json', ...corsHeaders }
      });
    }
  }
};
```

### Request Proxy with Modification
```javascript
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    
    // Modify request headers
    const modifiedRequest = new Request(request, {
      headers: {
        ...request.headers,
        'X-Custom-Header': 'Added by Worker',
        'Authorization': env.API_KEY
      }
    });
    
    // Proxy to origin
    const response = await fetch(modifiedRequest);
    
    // Modify response
    const modifiedResponse = new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers: {
        ...response.headers,
        'X-Processed-By': 'Cloudflare Worker'
      }
    });
    
    return modifiedResponse;
  }
};
```

## KV Storage Operations

### Basic KV Usage
```javascript
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    
    if (url.pathname === '/get') {
      const value = await env.MY_KV.get('key');
      return new Response(value || 'Not found');
    }
    
    if (url.pathname === '/set') {
      await env.MY_KV.put('key', 'value', {
        expirationTtl: 3600 // 1 hour
      });
      return new Response('Stored');
    }
    
    if (url.pathname === '/delete') {
      await env.MY_KV.delete('key');
      return new Response('Deleted');
    }
  }
};
```

### Manage KV Namespaces
```bash
# Create KV namespace
wrangler kv:namespace create "MY_NAMESPACE"
wrangler kv:namespace create "MY_NAMESPACE" --preview

# List KV pairs
wrangler kv:key list --namespace-id=your-namespace-id

# Put key-value
wrangler kv:key put --namespace-id=your-namespace-id "key" "value"

# Get value
wrangler kv:key get --namespace-id=your-namespace-id "key"

# Delete key
wrangler kv:key delete --namespace-id=your-namespace-id "key"

# Bulk upload
wrangler kv:bulk put --namespace-id=your-namespace-id data.json
```

## Environment Variables and Secrets

### Set Variables
```bash
# Set environment variable
wrangler secret put SECRET_KEY

# Set variable for specific environment
wrangler secret put SECRET_KEY --env production

# List secrets
wrangler secret list
wrangler secret list --env production

# Delete secret
wrangler secret delete SECRET_KEY
```

### Access in Worker
```javascript
export default {
  async fetch(request, env) {
    // Access environment variables
    const apiKey = env.SECRET_KEY;
    const dbUrl = env.DATABASE_URL;
    
    return new Response(`Using API key: ${apiKey}`);
  }
};
```

## Debugging and Monitoring

### View Logs
```bash
# Tail logs
wrangler tail

# Tail logs for specific environment
wrangler tail --env production

# Tail logs with filters
wrangler tail --status error
wrangler tail --method POST
wrangler tail --search "error"
```

### Analytics
```bash
# View analytics
wrangler analytics

# View analytics for date range
wrangler analytics --since 2023-01-01 --until 2023-01-31
```

## Decision Tree: Worker Use Cases

```
Need serverless function?
├── Simple API endpoint? → Basic Worker with fetch handler
├── Complex routing? → Use URLPattern or Router library
├── Database operations?
│   ├── Simple key-value? → Use KV storage
│   ├── SQL database? → Use D1 database binding
│   └── External API? → Use fetch with secrets
├── File processing? → Use Streams API
├── Authentication? → Implement JWT verification
└── Caching? → Use Cache API
```

## Troubleshooting

### Common Errors and Solutions

**Error**: `Error: No account found`
```bash
# Solution: Login again
wrangler login
# or check API token
wrangler whoami
```

**Error**: `Error: Unable to find the Worker script associated with this deployment`
```bash
# Solution: Ensure correct environment
wrangler publish --env production
# or check wrangler.toml configuration
```

**Error**: `Error: KV namespace not found`
```bash
# Solution: Create namespace and update wrangler.toml
wrangler kv:namespace create "MY_NAMESPACE"
# Add namespace ID to wrangler.toml
```

**Error**: `Error: Worker exceeded memory limit`
```javascript
// Solution: Optimize memory usage
export default {
  async fetch(request, env, ctx) {
    // Use streaming for large responses
    const { readable, writable } = new TransformStream();
    
    ctx.waitUntil(
      processLargeData(writable)
    );
    
    return new Response(readable);
  }
};
```

**Error**: `Error: Worker exceeded CPU time limit`
```javascript
// Solution: Use ctx.waitUntil for non-blocking operations
export default {
  async fetch(request, env, ctx) {
    // Quick response
    const response = new Response('Processing...');
    
    // Long-running task
    ctx.waitUntil(
      processInBackground(request, env)
    );
    
    return response;
  }
};
```

**Error**: `TypeError: env.MY_KV is undefined`
```toml
# Solution: Add KV binding to wrangler.toml
[[kv_namespaces]]
binding = "MY_KV"
id = "your-namespace-id"
```

### Debug Tips

```javascript
// Add logging for debugging
export default {
  async fetch(request, env, ctx) {
    console.log('Request URL:', request.url);
    console.log('Request method:', request.method);
    console.log('Request headers:', Object.fromEntries(request.headers));
    
    try {
      // Your logic here
      return new Response('Success');
    } catch (error) {
      console.error('Worker error:', error);
      return new Response('Error', { status: 500 });
    }
  }
};
```

curl -s https://skills.skynet.ceo/api/skills/cloudflare-workers/skill.md