cloudflare
Cloudflare Workers, Pages, D1, R2, KV, Durable Objects, DNS, and edge computing patterns
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
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/cloudflare/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How cloudflare Compares
| Feature / Agent | cloudflare | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/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
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
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
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
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
> TypeScript-first schema validation with static type inference.
webinar-registration-page
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
Webhook design patterns — delivery, retry with exponential backoff, HMAC signature verification, payload validation, idempotency keys
web-workers
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
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
Native Web Components, custom elements API, Shadow DOM, HTML templates, slots, lifecycle callbacks, and framework-agnostic design patterns
wasm
WebAssembly integration — Rust to WASM with wasm-pack/wasm-bindgen, WASI, browser usage, server-side WASM, and performance considerations
vue
Vue 3 Composition API, Nuxt patterns, reactivity system, component architecture, and production development practices