$npx -y skills add popmechanic/VibesOS --skill cloudflareSelf-contained deploy automation — invoke directly, do not decompose. Deploys a Vibes app to Cloudflare Workers via the Deploy API. Use when deploying, publishing, going live, pushing to production, or hosting on the edge.
| 1 | > **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. |
| 2 | |
| 3 | ``` |
| 4 | ╔═══════════════════════════════════════════════╗ |
| 5 | ║ ☁️ CLOUDFLARE WORKERS DEPLOY ║ |
| 6 | ║ Deploy API · Pocket ID · Edge Functions ║ |
| 7 | ╚═══════════════════════════════════════════════╝ |
| 8 | ``` |
| 9 | |
| 10 | ## Deploy to Cloudflare |
| 11 | |
| 12 | Deploy your Vibes app to Cloudflare Workers via the Deploy API. |
| 13 | |
| 14 | ### Prerequisites |
| 15 | |
| 16 | 1. **Assembled HTML file** (from `/vibes:vibes` or `/vibes:factory`) |
| 17 | 2. **Vibes account** (browser login on first deploy) |
| 18 | |
| 19 | No Cloudflare account or wrangler CLI needed — the Deploy API handles infrastructure. |
| 20 | |
| 21 | ### Quick Deploy |
| 22 | |
| 23 | ```bash |
| 24 | VIBES_ROOT="${CLAUDE_PLUGIN_ROOT:-$(dirname "$(dirname "${CLAUDE_SKILL_DIR}")")}" |
| 25 | bun "$VIBES_ROOT/scripts/deploy-cloudflare.js" --name myapp --file index.html |
| 26 | ``` |
| 27 | |
| 28 | On first run, a browser window opens for Pocket ID authentication. Tokens are cached for subsequent deploys. |
| 29 | |
| 30 | **Static Assets:** Place images, fonts, or other static files in an `assets/` directory next to the app file. The deploy script auto-discovers and includes them (binary files are base64-encoded). Reference in code with absolute paths like `/assets/logo.png`. |
| 31 | |
| 32 | ### Deploy with AI enabled |
| 33 | |
| 34 | ```bash |
| 35 | VIBES_ROOT="${CLAUDE_PLUGIN_ROOT:-$(dirname "$(dirname "${CLAUDE_SKILL_DIR}")")}" |
| 36 | bun "$VIBES_ROOT/scripts/deploy-cloudflare.js" --name myapp --file index.html --ai-key "sk-or-v1-your-key" |
| 37 | ``` |
| 38 | |
| 39 | The `--ai-key` flag configures the OpenRouter API key for the `useAI()` hook. Without it, `/api/ai/chat` returns `{"error": "AI not configured"}`. |
| 40 | |
| 41 | ### Endpoints |
| 42 | |
| 43 | | Endpoint | Method | Description | |
| 44 | |----------|--------|-------------| |
| 45 | | `/registry.json` | GET | Public registry read | |
| 46 | | `/check/:subdomain` | GET | Check subdomain availability | |
| 47 | | `/claim` | POST | Claim a subdomain (auth required) | |
| 48 | | `/api/ai/chat` | POST | AI proxy to OpenRouter (requires AI key) | |
| 49 | |
| 50 | ### Important: Custom Domain Required for Subdomains |
| 51 | |
| 52 | Workers.dev domains only support one subdomain level for SSL. For multi-tenant |
| 53 | apps with subdomains (tenant.myapp.workers.dev), you MUST use a custom domain. |
| 54 | |
| 55 | **Won't work:** `tenant.myapp.username.workers.dev` (SSL error) |
| 56 | **Will work:** `tenant.myapp.com` (with custom domain) |
| 57 | |
| 58 | On workers.dev, use the `?subdomain=` query parameter for testing: |
| 59 | - `myapp.username.workers.dev` → landing page |
| 60 | - `myapp.username.workers.dev?subdomain=tenant` → tenant app |
| 61 | - `myapp.username.workers.dev?subdomain=admin` → admin dashboard |
| 62 | |
| 63 | ### Custom Domain Setup |
| 64 | |
| 65 | 1. **Add domain to Cloudflare** (get nameservers from Cloudflare DNS dashboard) |
| 66 | 2. **Point registrar nameservers** to Cloudflare's assigned nameservers |
| 67 | 3. **Delete conflicting DNS records** for the apex domain (A, AAAA, CNAME) |
| 68 | 4. **Add Custom Domain** in Workers & Pages → your worker → Settings → Domains & Routes → Add → Custom Domain (apex: yourdomain.com) |
| 69 | 5. **Add wildcard CNAME** in DNS: Name: `*`, Target: `<worker-name>.<username>.workers.dev` (Proxied: ON) |
| 70 | 6. **Add Route** in Workers & Pages → your worker → Settings → Domains & Routes → Add → Route: `*.yourdomain.com/*` |
| 71 | |
| 72 | After setup: |
| 73 | - `yourdomain.com` → landing page |
| 74 | - `tenant.yourdomain.com` → tenant app |
| 75 | - `admin.yourdomain.com` → admin dashboard |
| 76 | |
| 77 | ### Troubleshooting |
| 78 | |
| 79 | | Problem | Cause | Fix | |
| 80 | |---------|-------|-----| |
| 81 | | Browser doesn't open for auth | Headless environment | Copy the printed URL and open manually | |
| 82 | | Deploy API returns 401 | Expired or invalid token | Delete `~/.vibes/auth.json` and retry | |
| 83 | | 404 on subdomain URL | Workers.dev doesn't support nested subdomains | Set up a custom domain (see Custom Domain Setup above) | |
| 84 | | `/api/ai/chat` returns "AI not configured" | Missing OpenRouter key | Redeploy with `--ai-key` | |
| 85 | | Stale content after redeploy | Browser cache | Hard refresh (Cmd+Shift+R) or clear cache | |
| 86 | |
| 87 | ### What's Next? |
| 88 | |
| 89 | After successful deployment, present these options: |
| 90 | |
| 91 | AskUserQuestion: |
| 92 | question: "Your app is deployed! What would you like to do next?" |
| 93 | header: "Next steps" |
| 94 | options: |
| 95 | - label: "Set up custom domain" |
| 96 | description: "Configure DNS for subdomain routing (required for multi-tenant)" |
| 97 | - label: "Enable AI features" |
| 98 | description: "Add OpenRouter API key for the useAI() hook" |
| 99 | - label: "Add auth & SaaS features" |
| 100 | description: "Transform into SaaS with /vibes:factory, then redeploy" |
| 101 | - label: "Open in browser" |
| 102 | description: "Visit the deployed URL to verify everything works" |