From indrasvat-skills
Deploy web apps, APIs, static sites, and edge functions to Cloudflare's free tier using wrangler and cloudflared CLIs. Use when user wants to (1) host/deploy a website, blog, or web app, (2) create serverless APIs or edge functions, (3) set up databases (SQL or KV), (4) store files/objects, (5) expose localhost via tunnel, (6) deploy any personal project to the cloud for free. Covers Workers, Pages, D1, KV, R2, Durable Objects, Workers AI, Tunnels, Email Routing. All deployments stay within $0 free tier limits.
How this skill is triggered — by the user, by Claude, or both
Slash command
/indrasvat-skills:cf-edgeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Deploy to Cloudflare's edge network at $0 cost. All services have free tiers sufficient for personal projects.
Deploy to Cloudflare's edge network at $0 cost. All services have free tiers sufficient for personal projects.
# Verify CLI tools
wrangler --version # Workers, Pages, D1, KV, R2
cloudflared --version # Tunnels
# If missing:
npm install -g wrangler
# cloudflared:
brew install cloudflare/cloudflare/cloudflared
wrangler pages project create <name>
wrangler pages deploy ./dist # or ./build, ./out, ./public
# Result: <name>.pages.dev — unlimited bandwidth
wrangler init <name> && cd <name>
wrangler dev # local: localhost:8787
wrangler deploy # live: <name>.<account>.workers.dev
wrangler d1 create <name>
wrangler d1 execute <name> --command "CREATE TABLE ..."
# Add to wrangler.toml: [[d1_databases]] binding/name/id
wrangler kv:namespace create <NAME>
# Add to wrangler.toml: [[kv_namespaces]] binding/id
wrangler r2 bucket create <name>
wrangler r2 object put <bucket>/path --file ./file
cloudflared tunnel --url http://localhost:3000 # instant public URL
| Service | Limit | Reset |
|---|---|---|
| Workers | 100K req/day, 10ms CPU/req | Daily UTC |
| Pages | Unlimited bandwidth, 500 builds/mo | Monthly |
| D1 | 5 GB storage, 5M reads/day, 100K writes/day | Daily UTC |
| KV | 1 GB storage, 100K reads/day, 1K writes/day | Daily UTC |
| R2 | 10 GB storage, $0 egress | Monthly |
| Durable Objects | 100K req/day, 5 GB storage | Daily UTC |
| Workers AI | 10K neurons/day (~500 LLM queries) | Daily UTC |
| Tunnels | Unlimited | — |
See references/limits.md for detailed breakdown.
name = "my-app"
main = "src/index.js" # or index.ts
compatibility_date = "2024-01-01"
# D1 Database
[[d1_databases]]
binding = "DB"
database_name = "my-db"
database_id = "<from wrangler d1 create>"
# KV Namespace
[[kv_namespaces]]
binding = "KV"
id = "<from wrangler kv:namespace create>"
# R2 Bucket
[[r2_buckets]]
binding = "BUCKET"
bucket_name = "my-bucket"
# Environment Variables
[vars]
ENVIRONMENT = "production"
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === '/api/data') {
const data = await env.DB.prepare('SELECT * FROM items').all();
return Response.json(data.results);
}
return new Response('Not Found', { status: 404 });
}
};
export default {
async fetch(request, env) {
// KV: fast reads, eventual consistency
const cached = await env.KV.get('key', 'json');
if (cached) return Response.json(cached);
// D1: SQL queries
const { results } = await env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(1).all();
// Cache result
await env.KV.put('key', JSON.stringify(results), { expirationTtl: 3600 });
return Response.json(results);
}
};
export default {
async fetch(request, env) {
const response = await env.AI.run('@cf/meta/llama-3.2-1b-instruct', {
prompt: 'Hello, how are you?'
});
return Response.json(response);
}
};
// Add to wrangler.toml: [ai] binding = "AI"
cloudflared tunnel login
cloudflared tunnel create <tunnel-name>
cloudflared tunnel route dns <tunnel-name> subdomain.yourdomain.com
# Create ~/.cloudflared/config.yml:
cat << EOF > ~/.cloudflared/config.yml
tunnel: <tunnel-id>
credentials-file: ~/.cloudflared/<tunnel-id>.json
ingress:
- hostname: subdomain.yourdomain.com
service: http://localhost:3000
- service: http_status:404
EOF
cloudflared tunnel run <tunnel-name>
wrangler d1 info <db> or check dashboardmy-project/
├── wrangler.toml
├── package.json
├── src/
│ └── index.js # Worker entry
├── public/ # Static assets (if using Pages)
└── migrations/ # D1 schema migrations
└── 0001_init.sql
# Development
wrangler dev # Local dev server
wrangler dev --remote # Dev against real services
# Deployment
wrangler deploy # Deploy Worker
wrangler pages deploy ./dist # Deploy Pages
# Database
wrangler d1 execute <db> --file ./migrations/001.sql
wrangler d1 execute <db> --command "SELECT * FROM users"
# Debugging
wrangler tail # Live logs
wrangler tail --format pretty # Formatted logs
# Info
wrangler whoami # Check auth
wrangler d1 info <db> # DB stats
references/limits.md — Detailed free tier limits and calculationsreferences/services.md — Full service configurations and patternsnpx claudepluginhub indrasvat/claude-code-skills --plugin indrasvat-skillsGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.