cloudflare
π―Skillfrom andrehfp/tinyplate
Automates Cloudflare domain configuration by setting up DNS records, integrating Clerk, configuring Vercel, and managing email routing.
Part of
andrehfp/tinyplate(8 items)
Installation
git clone git@github.com:andrehfp/tinyplate.gitSkill Details
"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."
Overview
# 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)
```bash
# 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
```bash
# Install wrangler
bun add -g wrangler
# Login (opens browser)
wrangler login
# Verify
wrangler whoami
```
Other Tools
```bash
# 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:
- Domain name (e.g.,
example.com) - Clerk DNS records (paste from Clerk dashboard)
- Vercel project name (e.g.,
my-app) - Email addresses to create (e.g.,
contact,support) - Redirect target email (e.g.,
me@gmail.com)
Step 2: Get Zone ID
```bash
# 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:
```bash
# 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
```bash
# 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:
```bash
# 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:
```bash
# 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": "your-main-email@gmail.com"
}'
# Create routing rule for contact@domain.com
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": ["your-main-email@gmail.com"]}]
}'
```
Required MX records for email routing:
```bash
# 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:
```bash
# 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?
> myemail@gmail.com
```
Common DNS Record Types
| Type | Use Case | Proxied |
|------|----------|---------|
| A | Root domain to IP | No (for Vercel) |
| CNAME | Subdomain to hostname | No (for Clerk/Vercel) |
| TXT | Verification, SPF | N/A |
| MX | Email routing | N/A |
Troubleshooting
| Issue | Solution |
|-------|----------|
| Zone not found | Domain must be added to Cloudflare first |
| DNS propagation slow | Wait 5-10 minutes, check with dig |
| Email not forwarding | Verify destination email first |
| Vercel 404 | Check DNS proxied=false for Vercel records |
| Clerk verification failed | Ensure TXT record is on root (@) |
Useful Commands
```bash
# 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?
- Create new bucket (full setup)
- Configure existing bucket (CORS, public access)
- Setup custom domain for bucket
```
Step 2: Gather Bucket Info
```
Bucket name?
> my-app-uploads
What will this bucket store?
- User uploads (images, files) - needs CORS + presigned URLs
- Static assets (public CDN) - needs public access
- Backups (private) - no public access
> 1
Custom domain? (optional, press enter to skip)
> uploads.myapp.com
```
Step 3: Create Bucket
```bash
# 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:
```json
{
"corsRules": [
{
"allowedOrigins": ["https://myapp.com", "http://localhost:3000"],
"allowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
"allowedHeaders": ["*"],
"exposeHeaders": ["ETag", "Content-Length"],
"maxAgeSeconds": 3600
}
]
}
```
Apply CORS:
```bash
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:
```bash
# 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)
- Go to R2 > Manage R2 API Tokens
- Create token with Object Read & Write
- Add to
.env.local:
```bash
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
```bash
# 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 Case | CORS | Public | Custom Domain |
|----------|------|--------|---------------|
| User uploads | Yes | No | Optional |
| Static assets/CDN | No | Yes | Recommended |
| Backups | No | No | No |
| Public downloads | No | Yes | Optional |
R2 Troubleshooting
| Issue | Solution |
|-------|----------|
| CORS error in browser | Add domain to allowedOrigins |
| 403 Forbidden | Check API token has R2:Edit permission |
| Custom domain not working | Ensure CNAME is proxied (orange cloud) |
| Upload fails | Verify Content-Type header matches file |
More from this repository7
ux-design skill from andrehfp/tinyplate
Optimizes Next.js apps with comprehensive technical SEO infrastructure, generating sitemaps, robots.txt, meta tags, structured data, and canonical URLs.
posthog skill from andrehfp/tinyplate
stripe skill from andrehfp/tinyplate
marketing-copy skill from andrehfp/tinyplate
abacatepay skill from andrehfp/tinyplate
Generates comprehensive favicons and app icons for Next.js projects, automatically detecting app details and creating multi-size icon sets.