cloudflare

Cloudflare Workers, Pages, D1, R2, KV, Durable Objects, DNS, and edge computing patterns

39 stars

Best use case

cloudflare is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Cloudflare Workers, Pages, D1, R2, KV, Durable Objects, DNS, and edge computing patterns

Teams using cloudflare should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/cloudflare/SKILL.md --create-dirs "https://raw.githubusercontent.com/InugamiDev/ultrathink-oss/main/.claude/skills/cloudflare/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/cloudflare/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How cloudflare Compares

Feature / AgentcloudflareStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Cloudflare Workers, Pages, D1, R2, KV, Durable Objects, DNS, and edge computing patterns

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Cloudflare Specialist

## Purpose

Design and implement edge-first applications using the Cloudflare platform. This skill covers Workers, Pages, D1 (SQLite at the edge), R2 (object storage), KV (key-value), Durable Objects, DNS management, and performance optimization patterns.

## Key Patterns

### Worker with Multiple Bindings

```typescript
// src/index.ts
export interface Env {
  DB: D1Database;
  KV: KVNamespace;
  R2: R2Bucket;
  RATE_LIMITER: DurableObjectNamespace;
  API_KEY: string;
}

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const url = new URL(request.url);

    try {
      if (url.pathname.startsWith("/api/")) {
        return handleAPI(request, env, ctx);
      }
      return new Response("Not Found", { status: 404 });
    } catch (error) {
      console.error("Worker error:", error);
      return new Response("Internal Server Error", { status: 500 });
    }
  },
} satisfies ExportedHandler<Env>;

async function handleAPI(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
  // Check KV cache first
  const cacheKey = new URL(request.url).pathname;
  const cached = await env.KV.get(cacheKey);
  if (cached) {
    return new Response(cached, {
      headers: { "Content-Type": "application/json", "X-Cache": "HIT" },
    });
  }

  // Query D1
  const result = await env.DB.prepare("SELECT * FROM posts WHERE published = 1 LIMIT 20").all();

  const json = JSON.stringify(result.results);

  // Cache in KV with TTL
  ctx.waitUntil(env.KV.put(cacheKey, json, { expirationTtl: 300 }));

  return new Response(json, {
    headers: { "Content-Type": "application/json", "X-Cache": "MISS" },
  });
}
```

### wrangler.toml Configuration

```toml
name = "my-app"
main = "src/index.ts"
compatibility_date = "2024-12-01"

[vars]
ENVIRONMENT = "production"

[[d1_databases]]
binding = "DB"
database_name = "my-app-db"
database_id = "xxx-xxx-xxx"

[[kv_namespaces]]
binding = "KV"
id = "xxx-xxx-xxx"

[[r2_buckets]]
binding = "R2"
bucket_name = "my-app-uploads"

[[durable_objects.bindings]]
name = "RATE_LIMITER"
class_name = "RateLimiter"

[[migrations]]
tag = "v1"
new_classes = ["RateLimiter"]

[triggers]
crons = ["*/5 * * * *"]
```

### D1 Database Patterns

```typescript
// Parameterized queries (always use bind parameters)
const user = await env.DB.prepare("SELECT * FROM users WHERE id = ?").bind(userId).first();

// Batch operations (single round trip)
const results = await env.DB.batch([
  env.DB.prepare("INSERT INTO orders (user_id, total) VALUES (?, ?)").bind(userId, total),
  env.DB.prepare("UPDATE inventory SET stock = stock - ? WHERE product_id = ?").bind(qty, productId),
]);

// Migrations
// wrangler d1 migrations create my-app-db create_users
// migrations/0001_create_users.sql
/*
CREATE TABLE users (
  id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
  email TEXT UNIQUE NOT NULL,
  name TEXT NOT NULL,
  created_at TEXT DEFAULT (datetime('now'))
);
CREATE INDEX idx_users_email ON users(email);
*/
```

### Durable Objects (Rate Limiter)

```typescript
export class RateLimiter implements DurableObject {
  private state: DurableObjectState;
  private requests: Map<string, number[]> = new Map();

  constructor(state: DurableObjectState, env: Env) {
    this.state = state;
  }

  async fetch(request: Request): Promise<Response> {
    const ip = request.headers.get("CF-Connecting-IP") || "unknown";
    const now = Date.now();
    const windowMs = 60_000; // 1 minute
    const maxRequests = 100;

    const timestamps = this.requests.get(ip) || [];
    const recent = timestamps.filter((t) => now - t < windowMs);

    if (recent.length >= maxRequests) {
      return new Response("Rate limit exceeded", {
        status: 429,
        headers: { "Retry-After": "60" },
      });
    }

    recent.push(now);
    this.requests.set(ip, recent);

    return new Response("OK", { status: 200 });
  }
}
```

### R2 Upload Pattern

```typescript
async function handleUpload(request: Request, env: Env): Promise<Response> {
  const formData = await request.formData();
  const file = formData.get("file") as File;

  if (!file) return new Response("No file", { status: 400 });

  const key = `uploads/${Date.now()}-${file.name}`;
  await env.R2.put(key, file.stream(), {
    httpMetadata: { contentType: file.type },
    customMetadata: { originalName: file.name },
  });

  return Response.json({ key, url: `/files/${key}` });
}
```

## Best Practices

### Performance
- Use KV for read-heavy data with eventual consistency tolerance
- Use D1 for relational data that needs consistency
- Use R2 for large objects (images, files, backups)
- Use Durable Objects for coordination and stateful logic
- Leverage `ctx.waitUntil()` for non-blocking async work (analytics, caching)
- Use `Cache API` for computed responses

### Security
- Always bind parameters in D1 queries (prevent SQL injection)
- Validate request origins with `request.headers.get("Origin")`
- Use `wrangler secret` for API keys, never `.env` files
- Implement rate limiting with Durable Objects or the Rate Limiting API
- Set CORS headers explicitly

### D1 Optimization
- Keep queries simple; D1 runs SQLite at the edge
- Use batch operations to minimize round trips
- Create indexes for frequently queried columns
- Use `RETURNING` clause to avoid extra reads after writes

### Deployment
- Use `wrangler deploy` with `--env` for staging vs production
- Test locally with `wrangler dev`
- Use `wrangler tail` for real-time log streaming
- Set up preview environments for PRs

## Common Pitfalls

| Pitfall | Fix |
|---------|-----|
| String interpolation in D1 queries | Always use `.bind()` parameters |
| Ignoring `ctx.waitUntil()` | Use it for fire-and-forget async work |
| KV reads in hot loops | Batch reads or use Cache API |
| Large Worker bundle | Use dynamic imports, tree shake |
| No error handling | Wrap handler in try/catch, log errors |
| Missing CORS headers | Add explicit `Access-Control-*` headers |

## Examples

### Cron Trigger (Scheduled Worker)

```typescript
export default {
  async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext) {
    // Runs every 5 minutes per wrangler.toml crons config
    const staleItems = await env.DB.prepare(
      "SELECT id FROM cache_entries WHERE expires_at < datetime('now')"
    ).all();

    if (staleItems.results.length > 0) {
      const ids = staleItems.results.map((r) => r.id);
      await env.DB.prepare(
        `DELETE FROM cache_entries WHERE id IN (${ids.map(() => "?").join(",")})`
      ).bind(...ids).run();
    }
  },
} satisfies ExportedHandler<Env>;
```

### Pages Functions (API Routes)

```typescript
// functions/api/posts.ts (Cloudflare Pages Functions)
export const onRequestGet: PagesFunction<Env> = async (context) => {
  const posts = await context.env.DB.prepare("SELECT * FROM posts LIMIT 20").all();
  return Response.json(posts.results);
};
```

Related Skills

ultrathink

39
from InugamiDev/ultrathink-oss

UltraThink Workflow OS — 4-layer skill mesh with persistent memory and privacy hooks for complex engineering tasks. Routes prompts through intent detection to activate the right domain skills automatically.

ultrathink_review

39
from InugamiDev/ultrathink-oss

Multi-pass code review powered by UltraThink's quality gate — checks correctness, security (OWASP), performance, readability, and project conventions in a single structured pass.

ultrathink_memory

39
from InugamiDev/ultrathink-oss

Persistent memory system for UltraThink — search, save, and recall project context, decisions, and patterns across sessions using Postgres-backed fuzzy search with synonym expansion.

ui-design

39
from InugamiDev/ultrathink-oss

Comprehensive UI design system: 230+ font pairings, 48 themes, 65 design systems, 23 design languages, 30 UX laws, 14 color systems, Swiss grid, Gestalt principles, Pencil.dev workflow. Inherits ui-ux-pro-max (99 UX rules) + impeccable-frontend-design (anti-AI-slop). Triggers on any design, UI, layout, typography, color, theme, or styling task.

Zod

39
from InugamiDev/ultrathink-oss

> TypeScript-first schema validation with static type inference.

webinar-registration-page

39
from InugamiDev/ultrathink-oss

Build a webinar or live event registration page as a self-contained HTML file with countdown timer, speaker bio, agenda, and registration form. Triggers on: "build a webinar registration page", "create a webinar sign-up page", "event registration landing page", "live training registration page", "workshop sign-up page", "create a webinar page", "build an event page", "free webinar landing page", "live demo registration page", "online event page", "create a registration page for my webinar", "build a training event page".

webhooks

39
from InugamiDev/ultrathink-oss

Webhook design patterns — delivery, retry with exponential backoff, HMAC signature verification, payload validation, idempotency keys

web-workers

39
from InugamiDev/ultrathink-oss

Offload heavy computation from the main thread using Web Workers, SharedWorkers, and Comlink — structured messaging, transferable objects, and off-main-thread architecture patterns

web-vitals

39
from InugamiDev/ultrathink-oss

Core Web Vitals monitoring (LCP, FID, CLS, INP, TTFB), measurement with web-vitals library, reporting to analytics, and optimization strategies for Next.js

web-components

39
from InugamiDev/ultrathink-oss

Native Web Components, custom elements API, Shadow DOM, HTML templates, slots, lifecycle callbacks, and framework-agnostic design patterns

wasm

39
from InugamiDev/ultrathink-oss

WebAssembly integration — Rust to WASM with wasm-pack/wasm-bindgen, WASI, browser usage, server-side WASM, and performance considerations

vue

39
from InugamiDev/ultrathink-oss

Vue 3 Composition API, Nuxt patterns, reactivity system, component architecture, and production development practices