sell
Self-contained SaaS automation — invoke directly, do not decompose. Transforms a Vibes app into a multi-tenant SaaS with subdomain-based tenancy. Adds Pocket ID authentication, subscription gating, and generates a unified app with landing page, tenant routing, and admin dashboard. Use when the user wants to monetize an app, add auth and billing, create a SaaS product, add subscriptions, or turn an app into a business.
git clone --depth 1 https://github.com/popmechanic/VibesOS /tmp/sell && cp -r /tmp/sell/vibes-desktop/build/stable-macos-arm64/VibesOS.app/Contents/Resources/vibes-plugin/skills/sell ~/.claude/skills/sellSKILL.md
> **Plan mode**: If you are planning work, this entire skill is ONE plan step: "Invoke /vibes:sell". Do not decompose the steps below into separate plan tasks.
**Display this ASCII art immediately when starting:**
```
░▒▓███████▓▒░▒▓████████▓▒░▒▓█▓▒░ ░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
░▒▓██████▓▒░░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
░▒▓███████▓▒░░▒▓████████▓▒░▒▓████████▓▒░▒▓████████▓▒░
```
## Quick Navigation
- [Critical Rules](#-critical-rules---read-first-) - Read this first
- [Step 1: Pre-Flight Checks](#step-1-pre-flight-checks) - Verify prerequisites
- [Step 2: App Identity](#step-2-app-identity) - Set up app name and deploy URL
- [Step 3: App Configuration](#step-3-app-configuration) - Collect app settings
- [Step 4: Assembly](#step-4-assembly) - Build the unified app
- [Step 5: Deployment](#step-5-deployment) - Deploy to Cloudflare Workers
- [Step 6: Post-Deploy Verification](#step-6-post-deploy-verification) - Confirm everything works
- [Key Components](#key-components) - Routing, TenantContext, SubscriptionGate
- [Troubleshooting](#troubleshooting) - Common issues and fixes
---
> **Assembly: transform (strip)** — `assemble-sell.js` receives a vibes-generated app.jsx and adapts it for the sell template. It strips `import` statements, `export default`, React destructuring, and template constants — because the sell template already provides all of these. All dependencies (`React`, TinyBase hooks, `useTenant`, `useState`, etc.) are available as globals.
## ⛔ CRITICAL RULES - READ FIRST ⛔
**DO NOT generate code manually.** This skill uses pre-built scripts:
| Step | Script | What it does |
|------|--------|--------------|
| Assembly | `assemble-sell.js` | Generates unified index.html |
| Deploy | `deploy-cloudflare.js` | Deploys to Cloudflare Workers with registry |
**Script location:**
```bash
VIBES_ROOT="${CLAUDE_PLUGIN_ROOT:-$(dirname "$(dirname "${CLAUDE_SKILL_DIR}")")}"
bun "$VIBES_ROOT/scripts/assemble-sell.js" ...
bun "$VIBES_ROOT/scripts/deploy-cloudflare.js" ...
```
**NEVER do these manually:**
- ❌ Write HTML/JSX for landing page, tenant app, or admin dashboard
- ❌ Generate routing logic or authentication code
**ALWAYS do these:**
- ✅ Complete pre-flight checks before starting
- ✅ Run `assemble-sell.js` to generate the unified app
- ✅ Deploy with `deploy-cloudflare.js`
---
# Sell - Transform Vibes to SaaS
This skill uses `assemble-sell.js` to inject the user's app into a pre-built template. The template contains security checks, Pocket ID auth integration, and TinyBase data patterns.
Convert your Vibes app into a multi-tenant SaaS product with:
- Subdomain-based tenancy (alice.yourdomain.com)
- Pocket ID authentication (with passkeys, automatic on deploy)
- Subscription gating (Stripe billing is phase 2)
- Per-tenant data isolation via TinyBase rooms (Durable Objects)
- Marketing landing page
- Admin dashboard
## Architecture
The sell skill generates a **single index.html** file that handles all routes via client-side subdomain detection:
```
yourdomain.com → Landing page
*.yourdomain.com → Tenant app with auth
admin.yourdomain.com → Admin dashboard
```
This approach simplifies deployment - you upload one file and it handles everything.
---
### Terminal or Editor UI?
Detect whether you're running in a terminal (Claude Code CLI) or an editor (Cursor, Windsurf, VS Code with Copilot). **Terminal agents** use `AskUserQuestion` for all input. **Editor agents** present requirements as a checklist comment, wait for user edits, then proceed. See the vibes skill for the full detection and interaction pattern.
## Step 1: Pre-Flight Checks
**Before starting, verify these prerequisites. STOP if any check fails.**
### 1.1 Auth Check
Auth is automatic — on first deploy, a browser window opens for Pocket ID login. Tokens are cached at `~/.vibes/auth.json` for subsequent deploys. No `.env` credential setup is needed.
### 1.2 Detect Existing App
```bash
ls -la app.jsx 2>/dev/null || echo "NOT_FOUND"
```
**If output shows `NOT_FOUND`:**
Check for riff directories:
```bash
ls -d riff-* 2>/dev/null
```
**Decision tree:**
- Found `app.jsx` → Proceed to Step 2
- Found multiple `riff-*/app.jsx` → Ask user to select one, then copy to `app.jsx`
- Found nothing → Tell user to run `/vibes:vibes` first
**STOP HERE** if no app exists. The sell skill transforms existing apps.
### 1.3 Pre-Flight Summary
After checks pass, confirm:
> "Pre-flight checks passed:
> - ✓ App found (app.jsx)
> - ✓ Auth is automatic via Pocket ID (browser login on first deploy)
>
> Now let's configure your app settings."
---
## Step 2: App Identity
### 2.1 Collect App Name (Needed for Deploy URL)
Collect the app name for deployment.
Use AskUserQuestion:
```
Question: "What should we call this app?"
Header: "App Name"
Options: Provide 2 suggestions based on context + user enters via "Other"
Description: "Used for database naming and deployment URL (e.g., 'wedding-photos')"
multiSelect: false
```
Store as `appName` (URL-safe slug: lowercase, hyphens, no special chars).
The app will be deployed via the Deploy API (`/vibes:cloudflare`), which assigns the domain automatically. Store `{appName}.vibes.diy` as `domain`.
---
## Step 3: App Configuration
**Use AskUserQuestion to collect all config in 2 batches.**
### Batch 1: Core Identity
App name and deploy domain were already resolved in Step 2.2. Custom domains can be configured later (Step 5.2).
Use the AskUserQuestion tool with these 2 questions:
```
Question 1: "Do you want to require paid subscriptions?"
Header: "Billing"
Options: ["No - free access for all", "Yes - subscription required"]
Description: "Billing via Stripe is planned for phase 2. Choose 'No' for now unless you have a custom Stripe integration."
Question 2: "Display title for your app?"Deploy Julian to an exe.xyz VM (new instance or update existing)
Self-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. Authenticates with Pocket ID.
Self-contained design transformer — invoke directly, do not decompose. Transforms a design reference HTML file into a Vibes app. Use when user provides a design.html, mockup, or static prototype to match exactly.
Self-contained SaaS pipeline — invoke directly, do not decompose. Generates a factory app with landing page, Stripe subscription checkout, Vibe Token economics, and deploys to Cloudflare Workers. Use when the user wants to monetize an app, add billing, create token-backed revenue sharing, or turn an app into a business.
Self-contained SaaS pipeline — invoke directly, do not decompose.
Self-contained parallel generator — invoke directly, do not decompose. Generates 3-10 app variations in parallel for comparing ideas. Use when user says "explore options", "give me variations", "riff on this", "brainstorm approaches", or wants to see multiple interpretations of a concept.
Lightweight requirements gathering before app generation. Asks non-technical multiple-choice questions to understand user intent, then produces a brief for the generate prompt.
Self-contained app generator — invoke this skill directly, do not decompose into sub-steps. Generates React web apps with TinyBase reactive data store. Use when creating new web applications, adding components, or working with real-time data. Ideal for quick prototypes and single-page apps that need real-time data sync.