Vibecodr - How It Works

This document describes how Vibecodr actually works, step by step, based on the implemented architecture. It follows a request from the browser through the web app, API Worker, execution workers, and back.

1. Web App and API Boundary

The web UI is a React single-page app (apps/web) that uses React Router for client-side navigation. All data comes from an edge Worker API whose base URL is computed by helpers in the web app.

A typical browser request follows this path:

  1. User navigates to a route like /, /player/:postId, or /settings
  2. The SPA route component uses an API helper to call the Worker API (e.g., GET /posts, GET /profile/:handle)
  3. The API Worker reads/writes from D1, R2, Durable Objects, and Analytics Engine
  4. The route component maps the JSON response into view models and renders the page
Browser -> React SPA -> API Worker -> D1/R2/KV/DO -> Response -> SPA renders

Key idea: All data flows through a single API Worker endpoint. The SPA never talks directly to storage services.

2. Feed and Post Flow

The home feed and post views are backed by feed endpoints in the API worker:

The SPA uses shared schemas from @vibecodr/shared to validate API responses before mapping them into feed and player models.

3. Feed Ranking and Personalization

Feed ranking uses linear, non-ML scoring over existing signals to keep behavior auditable while allowing future model swaps without API changes.

Signals Used

Feed Modes

Safety Filters

Excludes muted/blocked users, quarantined content; applies search/tag filters before scoring; falls back to discover feed if personalization is empty.

4. Vibe Runtime Execution

When a user opens a vibe in the player at /player/:postId, the system loads and runs that vibe in a sandboxed iframe:

  1. Player page fetches the post and associated runtime manifest from the Worker API
  2. Player enforces client-side runtime budgets (max concurrent runners, boot timeouts by surface and plan)
  3. Player selects an execution origin: prefers https://c-<capsuleId>-rt.vxbe.space/__vibecodr/frame (optional ?artifactId=...) and preview uses https://<slug>-rt.vxbe.space/__vibecodr/preview; if unavailable, fall back to opaque null origin
  4. Runtime HTML and bundle load in a sandboxed iframe with strict CSP. Cross-origin runtimes may use sandbox="allow-same-origin" because the runtime origin is not on vibecodr.space
  5. The iframe runs user code purely client-side; there is no server-side Node.js runtime
  6. Iframe and host communicate via postMessage protocol carrying params, logs, and telemetry
  7. Logs and runtime events are forwarded to the Worker; runs are finalized via runtime completion APIs
Player Page -> Fetch Manifest -> Load Iframe (sandbox + CSP) v Iframe runs vibe code (client-only) v postMessage bridge <-> Host SPA v Telemetry -> API Worker -> D1/Analytics Engine

Key idea: Vibes execute entirely in the browser. The iframe is sandboxed and communicates with the host only via postMessage. No server-side Node.js runtime.

Dependency loading is deterministic and recorded in the runtime manifest:

Runtime Budgets

5. Pulse Execution Flow

Pulses are per-user server-side functions deployed on Workers for Platforms. The execution path is implemented in the API Worker and dispatch worker.

  1. Pulse is created and managed via pulse APIs in workers/api
  2. Deployment scripts build and deploy a per-pulse Worker using the template in workers/vibe-template
  3. Manual runs are quota-checked against the user's plan in the API Worker
  4. Vibes and triggers call POST /pulses/:id/run (Clerk for private pulses; public/unlisted can be anonymous - no account required)
  5. Dispatch worker validates grant, enforces rate limits and concurrency caps, checks kill switches
  6. Dispatch routes to the user's pulse Worker in the dispatch namespace
  7. Pulse Worker returns a Response or JSON result; dispatch attaches metadata headers
Vibe iframe -> postMessage("pulse:run") -> Host SPA v POST /pulses/:id/run (Clerk for private; public/unlisted anonymous - no account required) -> API Worker -> Dispatch Worker v Dispatch validates grant, enforces limits -> User's Pulse Worker v Response -> Host SPA -> postMessage -> Vibe iframe

Key idea: Browser only talks to API Worker; dispatch uses short-lived grants minted by the API, and grants are only required when you cannot attach Clerk or when calling dispatch directly.

6. Secrets and Proxy Flow

Pulse secrets are stored encrypted in D1 and accessed via a zero-gap protection model.

  1. User creates secrets via /me/secrets; secrets are stored encrypted with AES-256-GCM
  2. Secrets can be bound to specific pulses via /pulses/:id/secrets
  3. Pulse code calls env.secrets.fetch(url, { secret: "key" }) to make authenticated requests
  4. The dispatch worker intercepts these requests, injects the secret value server-side, and returns the response
  5. Raw secret values are never exposed to user code-only key names via env.secrets.keys()

SSRF + Infra Blocklist

Dispatch proxy egress (secrets, token, and connections fetch) enforces the Vibecodr infra blocklist, validates per-secret allowlists when configured, blocks private/loopback/metadata IP ranges, and re-checks every redirect hop.

7. Safety, Limits, and Plans

Safety and cost controls are implemented across the API Worker, dispatch worker, and shared config:

Plan Limits Summary

Plan Price Storage Bundle Pulses Runs/mo
Free $0 1 GB 10 MB 3 1,500
Creator $9/mo 5 GB 50 MB 15 150,000
Pro $39/mo 25 GB 100 MB 50 1,000,000

See /pricing for current pricing. Limits defined in packages/shared/src/plans.ts.

8. Real-time Streams

Vibecodr provides SSE streams for admin analytics:

Notifications use client-side SWR polling (GET /notifications/unread-count) for cost efficiency. Streams send heartbeats to keep connections alive; clients back off on 429/5xx and retain REST endpoints as fallback.

9. Key API Endpoints

Anchor endpoints organized by domain:

Domain Endpoints Purpose
Feed/Read GET /feed/discover, GET /feed/following, GET /feed/for-you, GET /posts/discover Feed modes (latest via mode=latest, discover, following, for-you), search, tags
Posts GET/POST /posts/:id, /like, /comments CRUD, social interactions
Capsules GET /capsules/:id, /manifest, /bundle Vibe container data, runtime manifest, compiled bundles
Pulse CRUD GET/POST /pulses, PATCH/DELETE /pulses/:id Manage server-side functions
Pulse Run POST /pulses/:id/run (public/unlisted), POST /pulse-grants (private/external) Execution; grants only when Clerk auth is not available
Secrets GET/POST /me/secrets, GET/POST /pulses/:id/secrets Manage encrypted secrets for pulse authentication
Connections GET /me/connections, POST /me/connections/:provider/start, DELETE /me/connections/:provider OAuth connections for pulses (tokens never exposed to user code)
Webhooks POST /t/:triggerId Inbound webhook entry point for http_webhook triggers
Triggers GET/POST /triggers, PATCH /triggers/:id, POST /triggers/validate-cron Automation rules, cron validation, and action management
Profiles GET /users/:handle, GET /profile/:handle User profiles, follow relationships

10. Studio Keyboard Shortcuts

The Studio IDE uses Alt-based keyboard shortcuts to avoid conflicts with browser shortcuts (Ctrl/Cmd). Here's the complete reference:

Category Shortcut Action
File Operations Alt+S Save current file
Alt+Enter Publish project
Panel Toggles Alt+E Toggle file sidebar
Alt+P Toggle preview panel
Alt+B Toggle config panel
Alt+J Toggle console panel
Alt+/ Toggle hints panel
Alt+Shift+M Toggle problems panel
Editor Alt+\ Toggle split editor
Search Alt+Shift+F Find in files
Alt+H Find and replace
Tab Management Alt+W Close current tab
Alt+Shift+T Reopen closed tab
Alt+Left/Right Navigate between tabs
Alt+1-9 Jump to tab by number
Error Navigation F8 Go to next error
Shift+F8 Go to previous error

Note: All shortcuts use Alt modifier to avoid conflicts with browser shortcuts. Access the full reference in Studio via Help > Keyboard Shortcuts.

11. Image/Asset Support

Agent guidance for assets and images:

<!-- HTML -->
<img src="assets/products/shirt.png" alt="" />

/* CSS */
.hero {
  background-image: url("assets/products/shirt.png");
}

// React
import shirtUrl from "./assets/products/shirt.png";
<img src={shirtUrl} alt="" />

12. Architecture Summary

Taken together, these flows describe how a request moves through Vibecodr: from the browser into Workers, through D1/R2/Durable Objects and back, using only the behavior defined in the codebase.

BROWSER React SPA (apps/web) -> postMessage -> Vibe Iframe (sandbox) | v HTTPS API WORKER (workers/api) Routes, Auth, Quotas, Feed Ranking, Capsule/Pulse Management D1 (SQLite) <-> R2 (Storage) <-> KV <-> Durable Objects | v Grant-based dispatch DISPATCH WORKER (workers/dispatch) Grant validation, Rate limits, Concurrency caps, Kill switches | v USER PULSE WORKERS (Workers for Platforms) Per-user isolated Workers running pulse code with scoped tools

Key idea: Three-layer architecture. Browser SPA handles UI. API Worker handles data and orchestration. Dispatch Worker routes to isolated per-user pulse Workers. Each layer adds security/isolation.