AS
AgSkills.dev
MARKETPLACE

cloudflare

Setup domains in Cloudflare with DNS for Clerk, Vercel, and email routing. Use when adding new domains, configuring DNS records, or setting up email redirects.

48
27

Preview

SKILL.md
name
cloudflare
description
"Setup domains in Cloudflare with DNS for Clerk, Vercel, and email routing. Use when adding new domains, configuring DNS records, or setting up email redirects."
allowed-tools
Read, Glob, Grep, Write, Edit, Bash, WebSearch

Cloudflare Setup

Automate Cloudflare workflows: DNS setup, Clerk integration, Vercel deployment, email routing, and R2 storage.

Prerequisites

Authentication (Choose One)

Option 1: API Token (Recommended)

# Add to .env.local CLOUDFLARE_API_TOKEN="your-api-token" CLOUDFLARE_ACCOUNT_ID="your-account-id"

Create token at: https://dash.cloudflare.com/profile/api-tokens Required permissions:

  • Zone:DNS:Edit
  • Zone:Zone:Read
  • Email Routing Addresses:Edit
  • Email Routing Rules:Edit
  • Account:R2:Edit (for R2 storage)

Option 2: Wrangler CLI

# Install wrangler bun add -g wrangler # Login (opens browser) wrangler login # Verify wrangler whoami

Other Tools

# Vercel CLI (required) bun add -g vercel vercel login

Workflow

When setting up a new domain, follow these steps:

Step 1: Gather Information

Ask the user for:

  1. Domain name (e.g., example.com)
  2. Clerk DNS records (paste from Clerk dashboard)
  3. Vercel project name (e.g., my-app)
  4. Email addresses to create (e.g., contact, support)
  5. Redirect target email (e.g., [email protected])

Step 2: Get Zone ID

# If using API token curl -X GET "https://api.cloudflare.com/client/v4/zones?name=DOMAIN" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Content-Type: application/json" | jq '.result[0].id' # If using wrangler wrangler pages project list # Shows associated zones

Step 3: Create DNS Records for Clerk

Clerk provides specific DNS records for each project. Common patterns:

# Example: CNAME record curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "type": "CNAME", "name": "clerk", "content": "frontend-api.clerk.dev", "ttl": 1, "proxied": false }' # Example: TXT record for verification curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "type": "TXT", "name": "@", "content": "clerk-verification=xxxxx", "ttl": 1 }'

Step 4: Add Domain to Vercel

# Add domain to Vercel project vercel domains add DOMAIN --scope=TEAM_SLUG # Or link to specific project vercel domains add DOMAIN PROJECT_NAME

Then create Vercel DNS records:

# A record for root domain curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "type": "A", "name": "@", "content": "76.76.21.21", "ttl": 1, "proxied": false }' # CNAME for www subdomain curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "type": "CNAME", "name": "www", "content": "cname.vercel-dns.com", "ttl": 1, "proxied": false }'

Step 5: Setup Email Routing

First, enable email routing for the zone (do this in Cloudflare dashboard first time).

Then create routing rules:

# Create destination address (must be verified first) curl -X POST "https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/email/routing/addresses" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "email": "[email protected]" }' # Create routing rule for [email protected] curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/email/routing/rules" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "name": "Forward contact", "enabled": true, "matchers": [{"type": "literal", "field": "to", "value": "contact@DOMAIN"}], "actions": [{"type": "forward", "value": ["[email protected]"]}] }'

Required MX records for email routing:

# MX records for Cloudflare Email Routing curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "type": "MX", "name": "@", "content": "route1.mx.cloudflare.net", "priority": 69, "ttl": 1 }' curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "type": "MX", "name": "@", "content": "route2.mx.cloudflare.net", "priority": 46, "ttl": 1 }' curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "type": "MX", "name": "@", "content": "route3.mx.cloudflare.net", "priority": 89, "ttl": 1 }' # TXT record for SPF curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "type": "TXT", "name": "@", "content": "v=spf1 include:_spf.mx.cloudflare.net ~all", "ttl": 1 }'

Step 6: Verification Checklist

After setup, verify:

# List all DNS records curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | jq '.result[] | {type, name, content}' # Check Vercel domain status vercel domains inspect DOMAIN # Test email routing (send test email to contact@DOMAIN)

Interactive Prompts Template

When running /cloudflare, ask:

What domain are you setting up?
> example.com

Paste the Clerk DNS records from your Clerk dashboard:
> [user pastes records]

What's the Vercel project name?
> my-saas-app

What email addresses should I create? (comma-separated)
> contact, support, hello

What email should these redirect to?
> [email protected]

Common DNS Record Types

TypeUse CaseProxied
ARoot domain to IPNo (for Vercel)
CNAMESubdomain to hostnameNo (for Clerk/Vercel)
TXTVerification, SPFN/A
MXEmail routingN/A

Troubleshooting

IssueSolution
Zone not foundDomain must be added to Cloudflare first
DNS propagation slowWait 5-10 minutes, check with dig
Email not forwardingVerify destination email first
Vercel 404Check DNS proxied=false for Vercel records
Clerk verification failedEnsure TXT record is on root (@)

Useful Commands

# Check DNS propagation dig DOMAIN +short dig DOMAIN MX +short dig DOMAIN TXT +short # List zones in account curl -X GET "https://api.cloudflare.com/client/v4/zones" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | jq '.result[] | {name, id}' # Delete a DNS record curl -X DELETE "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records/RECORD_ID" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"

R2 Storage Setup

Setup R2 buckets for file storage: user uploads, static assets, backups.

R2 Workflow

Step 1: Determine Use Case

Ask the user:

What do you want to do with R2?
1. Create new bucket (full setup)
2. Configure existing bucket (CORS, public access)
3. Setup custom domain for bucket

Step 2: Gather Bucket Info

Bucket name?
> my-app-uploads

What will this bucket store?
1. User uploads (images, files) - needs CORS + presigned URLs
2. Static assets (public CDN) - needs public access
3. Backups (private) - no public access
> 1

Custom domain? (optional, press enter to skip)
> uploads.myapp.com

Step 3: Create Bucket

# Create bucket via wrangler wrangler r2 bucket create my-app-uploads # Or via API curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/r2/buckets" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Content-Type: application/json" \ --data '{"name": "my-app-uploads", "locationHint": "wnam"}'

Step 4: Configure CORS (for user uploads)

Create cors.json:

{ "corsRules": [ { "allowedOrigins": ["https://myapp.com", "http://localhost:3000"], "allowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"], "allowedHeaders": ["*"], "exposeHeaders": ["ETag", "Content-Length"], "maxAgeSeconds": 3600 } ] }

Apply CORS:

wrangler r2 bucket cors put my-app-uploads --file=cors.json

Step 5: Setup Public Access (for static assets)

Option A: Enable R2.dev subdomain (via dashboard)

  • Go to R2 > Bucket > Settings > Public access

Option B: Custom domain:

# Add CNAME record curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "type": "CNAME", "name": "uploads", "content": "{account_id}.r2.cloudflarestorage.com", "ttl": 1, "proxied": true }'

Then enable custom domain in R2 bucket settings.

Step 6: Generate S3 API Credentials (for SDK access)

  1. Go to R2 > Manage R2 API Tokens
  2. Create token with Object Read & Write
  3. Add to .env.local:
R2_ACCESS_KEY_ID="your-access-key" R2_SECRET_ACCESS_KEY="your-secret-key" R2_ENDPOINT="https://{account_id}.r2.cloudflarestorage.com" R2_BUCKET_NAME="my-app-uploads"

R2 Quick Commands

# List buckets wrangler r2 bucket list # Create bucket wrangler r2 bucket create BUCKET_NAME # Delete bucket wrangler r2 bucket delete BUCKET_NAME # List objects wrangler r2 object list BUCKET_NAME # Upload file wrangler r2 object put BUCKET_NAME/path/file.png --file=./local.png # View CORS config wrangler r2 bucket cors get BUCKET_NAME

R2 Use Case Presets

Use CaseCORSPublicCustom Domain
User uploadsYesNoOptional
Static assets/CDNNoYesRecommended
BackupsNoNoNo
Public downloadsNoYesOptional

R2 Troubleshooting

IssueSolution
CORS error in browserAdd domain to allowedOrigins
403 ForbiddenCheck API token has R2:Edit permission
Custom domain not workingEnsure CNAME is proxied (orange cloud)
Upload failsVerify Content-Type header matches file
GitHub Repository
andrehfp/tinyplate
Stars
48
Forks
27
Open Repository
Install Skill
Download ZIP5 files