cloudflare
npx skills add https://github.com/popmechanic/vibes-cli --skill cloudflare
Agent 安装分布
Skill 文档
Plan mode: If you are planning work, this entire skill is ONE plan step: “Invoke /vibes:cloudflare”. Do not decompose the steps below into separate plan tasks.
âââââââââââââââââââââââââââââââââââââââââââââââââ
â âï¸ CLOUDFLARE WORKERS DEPLOY â
â KV Registry · JWT Auth · Edge Functions â
âââââââââââââââââââââââââââââââââââââââââââââââââ
Deploy to Cloudflare
Deploy your Vibes app to Cloudflare Workers with the subdomain registry.
Prerequisites
- Cloudflare account with Workers enabled
- Wrangler CLI installed (
npm install -g wrangler) - KV namespace created for registry storage
Quick Deploy
cd skills/cloudflare/worker
npm install
wrangler deploy
Environment Setup
Before deploying, set the required secrets:
cd skills/cloudflare/worker
npx wrangler secret put CLERK_PEM_PUBLIC_KEY
npx wrangler secret put CLERK_WEBHOOK_SECRET
Deploy Script
For deploying with static assets (index.html, bundles, assets):
node scripts/deploy-cloudflare.js --name myapp --file index.html --clerk-key "pk_test_xxx"
The --clerk-key flag auto-fetches the PEM public key from Clerk’s JWKS endpoint and sets it as CLERK_PEM_PUBLIC_KEY. Without it, the Worker can’t verify JWTs for authenticated endpoints like /claim.
This automatically:
- Copies index.html to worker’s public/
- Copies bundles/*.js (fireproof-vibes-bridge.js + fireproof-clerk-bundle.js)
- Copies assets/ directory (images, icons)
- Runs wrangler deploy
Endpoints
| Endpoint | Method | Description |
|---|---|---|
/registry.json |
GET | Public registry read |
/check/:subdomain |
GET | Check subdomain availability |
/claim |
POST | Claim a subdomain (auth required) |
/webhook |
POST | Clerk subscription webhooks |
/api/ai/chat |
POST | AI proxy to OpenRouter (requires OPENROUTER_API_KEY) |
KV Storage
The registry is stored in Cloudflare KV under the key registry. Schema:
{
"claims": { "subdomain": { "userId": "...", "claimedAt": "..." } },
"reserved": ["admin", "api", "www"],
"preallocated": {}
}
Important: Custom Domain Required for Subdomains
Workers.dev domains only support one subdomain level for SSL. For multi-tenant apps with subdomains (tenant.myapp.workers.dev), you MUST use a custom domain.
Won’t work: tenant.myapp.username.workers.dev (SSL error)
Will work: tenant.myapp.com (with custom domain)
On workers.dev, use the ?subdomain= query parameter for testing:
myapp.username.workers.devâ landing pagemyapp.username.workers.dev?subdomain=tenantâ tenant appmyapp.username.workers.dev?subdomain=adminâ admin dashboard
Custom Domain Setup
- Add domain to Cloudflare (get nameservers from Cloudflare DNS dashboard)
- Point registrar nameservers to Cloudflare’s assigned nameservers
- Delete conflicting DNS records for the apex domain (A, AAAA, CNAME)
- Add Custom Domain in Workers & Pages â your worker â Settings â Domains & Routes â Add â Custom Domain (apex: yourdomain.com)
- Add wildcard CNAME in DNS: Name:
*, Target:<worker-name>.<username>.workers.dev(Proxied: ON) - Add Route in Workers & Pages â your worker â Settings â Domains & Routes â Add â Route:
*.yourdomain.com/*
After setup:
yourdomain.comâ landing pagetenant.yourdomain.comâ tenant appadmin.yourdomain.comâ admin dashboard
Required Secrets
| Secret | Source | Purpose |
|---|---|---|
CLERK_PEM_PUBLIC_KEY |
Clerk JWKS endpoint | JWT signature verification |
PERMITTED_ORIGINS |
Your domains | JWT azp claim validation |
CLERK_WEBHOOK_SECRET |
Clerk dashboard | Webhook signature verification |
OPENROUTER_API_KEY |
OpenRouter dashboard | AI proxy for useAI() hook (optional) |
Setting secrets:
cd skills/cloudflare/worker
npx wrangler secret put CLERK_PEM_PUBLIC_KEY
# Paste the PEM key (-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----)
npx wrangler secret put CLERK_WEBHOOK_SECRET
# Paste the webhook signing secret from Clerk dashboard
npx wrangler secret put PERMITTED_ORIGINS
# Enter: https://yourdomain.com,https://*.yourdomain.com
Getting CLERK_PEM_PUBLIC_KEY:
- Find your Clerk Frontend API URL in Clerk dashboard (e.g.,
clerk.yourdomain.com) - Fetch JWKS:
curl https://clerk.yourdomain.com/.well-known/jwks.json - Convert JWK to PEM using Node.js:
const crypto = require('crypto');
const jwk = { /* paste the key from jwks.json */ };
const pem = crypto.createPublicKey({ key: jwk, format: 'jwk' }).export({ type: 'spki', format: 'pem' });
console.log(pem);
Deploy with –name Flag
Always use the --name flag to deploy to your app’s worker:
node scripts/deploy-cloudflare.js --name myapp --file index.html
Important: The --name determines the worker URL. Without it, wrangler uses
the name from wrangler.toml (vibes-registry), not your app.
AI Features
Apps using the useAI() hook call /api/ai/chat on the same origin. The worker proxies these requests to OpenRouter.
Deploy with AI enabled:
node scripts/deploy-cloudflare.js --name myapp --file index.html --clerk-key "pk_test_xxx" --ai-key "sk-or-v1-your-key"
The --ai-key flag sets the OPENROUTER_API_KEY secret on the worker after deployment. Without it, /api/ai/chat returns {"error": "AI not configured"}.
Manual setup:
npx wrangler secret put OPENROUTER_API_KEY --name myapp
# Paste your OpenRouter API key
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
wrangler: command not found |
Wrangler not installed | npm install -g wrangler or use npx wrangler |
| KV namespace errors | Namespace doesn’t exist or wrong ID | Run npx wrangler kv namespace list to verify |
| JWT verification fails (401) | Missing or wrong PEM key | Check CLERK_PEM_PUBLIC_KEY is set: npx wrangler secret list --name <app> |
| JWT azp mismatch (403) | Origins not configured | Set PERMITTED_ORIGINS to include your domain |
| 404 on subdomain URL | Workers.dev doesn’t support nested subdomains | Set up a custom domain (see Custom Domain Setup above) |
/api/ai/chat returns “AI not configured” |
Missing OpenRouter key | Set OPENROUTER_API_KEY secret or redeploy with --ai-key |
wrangler deploy auth error |
Not logged in | Run npx wrangler login |
| Stale content after redeploy | Browser cache | Hard refresh (Cmd+Shift+R) or clear cache |
What’s Next?
After successful deployment, present these options:
AskUserQuestion: question: “Your app is deployed! What would you like to do next?” header: “Next steps” options: – label: “Set up custom domain” description: “Configure DNS for subdomain routing (required for multi-tenant)” – label: “Enable AI features” description: “Add OpenRouter API key for the useAI() hook” – label: “Add billing & auth” description: “Transform into SaaS with /vibes:sell, then redeploy” – label: “Open in browser” description: “Visit the deployed URL to verify everything works”