Skip to main content
Vibra Code connects three distinct environments — your phone, a Next.js backend, and E2B cloud sandboxes — through a real-time pipeline. This page explains how those pieces fit together and what happens at each stage when you describe an app.

System diagram

  Phone                     Server                        Cloud
┌──────────┐   API    ┌──────────────┐   Queue    ┌──────────────┐
│  Expo    │ ──────── │   Next.js    │ ────────── │  E2B Sandbox │
│  iOS App │          │   + Convex   │   Inngest  │  + AI Agent  │
└────┬─────┘          └──────┬───────┘            └──────┬───────┘
     │                       │                           │
     └───── real-time sync ──┴─── code generation ───────┘
The phone never talks to the sandbox directly. All communication flows through the backend and Convex, which decouples the mobile client from the long-running build process and lets the phone reconnect at any time without losing progress.

Data flow

1

User describes an app

The user types or speaks a description in VibraCreateAppScreen. The mobile app calls the backend API (POST /api/create-session) with the prompt, chosen template, and any attached images or audio.
2

Session created in Convex

The backend creates a sessions record in Convex with status IN_PROGRESS. The mobile app subscribes to this session via Convex’s real-time client — any future status change streams to the phone immediately.
3

Inngest queues sandbox creation

The backend triggers an Inngest event that queues the create-session function. Inngest handles retries, timeouts, and fan-out, so the Next.js request returns immediately without waiting for the sandbox to be ready.
4

E2B sandbox starts and clones the template

The create-session Inngest function spawns an E2B sandbox from the pre-built template image. Inside the sandbox, the Expo template repository is cloned, npm dependencies are installed, the Expo dev server is started, and a public tunnel URL is created. The session status in Convex advances through each phase:IN_PROGRESSCLONING_REPOINSTALLING_DEPENDENCIESSTARTING_DEV_SERVERCREATING_TUNNELRUNNING
5

AI agent generates code

Once the sandbox is ready, Inngest runs the run-agent function. The AI agent (Claude Code, Cursor, or Gemini — configured by AGENT_TYPE) reads the user’s prompt and system prompt from lib/prompts.ts, then writes, edits, and runs files inside the sandbox. Every tool operation (file read, file edit, bash command) is written to the messages table in Convex as it happens.
6

Updates stream to the phone in real time

The mobile app’s Convex subscription receives each new messages record the moment it is written. The native chat UI (built with Texture + IGListKit) renders each message type in a different cell: blue for file reads, orange for file edits, green for bash commands, and Liquid Glass cards for todo task lists.
7

Phone previews the running app via tunnel URL

When the tunnel URL is available in the sessions record, the mobile app loads the live preview. For Expo React Native templates, the preview renders natively. For Next.js and other web templates, a WKWebView is used. The user can send follow-up messages to the same session — the agent resumes in the existing sandbox without re-cloning.

Backend stack

ComponentTechnologyPurpose
API serverNext.js 15 (App Router)Handles client requests, webhooks, and server actions
Real-time databaseConvexStores sessions, messages, and users; streams changes to clients
Background jobsInngestQueues and runs create-session, run-agent, and push-to-github
Cloud sandboxesE2BIsolated environments for code generation and execution
AI agentClaude Agent SDK / Cursor / Gemini CLIWrites and edits project files inside the sandbox
AuthClerkUser identity for both backend and mobile app
PaymentsStripe (web) + RevenueCat (mobile)Optional subscription billing

Mobile stack

ComponentTechnologyPurpose
RuntimeReact Native / Expo SDK 54Cross-platform native mobile foundation
AuthClerkShared with backend; same user identity
Real-time syncConvexSymlinked schema from backend; subscribes to sessions and messages
Chat UITexture (AsyncDisplayKit) + IGListKit60 fps off-main-thread rendering
NavigationReact NavigationStack + bottom tab navigator (Home, Create, Profile)
In-app purchasesRevenueCatOptional mobile subscription management

Convex schema overview

The Convex database is shared between the backend and mobile app. The mobile convex/ directory is a symlink to vibracode-backend/convex/.

users table

Stores Clerk user profiles alongside billing and credit state.
FieldTypeDescription
clerkIdstringPrimary identifier from Clerk
subscriptionPlanstringfree, weekly_plus, pro, business, enterprise
billingModetokens | creditsToken mode for Cursor agent; credit mode for Claude agent
creditsUSDnumberAvailable credits (Claude agent, 2× multiplier of real cost)
messagesRemainingnumberMessages remaining this period (Cursor/token mode)
agentTypeclaude | cursor | geminiPer-user agent override
pushTokenstringExpo push token for notifications

sessions table

Each build is one session. The session record tracks the full lifecycle from sandbox creation to completion.
FieldTypeDescription
namestringApp name provided by the user
templateIdstringWhich template was used (expo, nextjs, etc.)
statusunionCurrent phase — see session status lifecycle below
tunnelUrlstringPublic preview URL from the sandbox tunnel
totalCostUSDnumberAccumulated AI API cost for this session
envsrecordEnvironment variables injected into the sandbox
githubRepositorystringPopulated after a GitHub push (owner/repo)

messages table

Every agent action and user message is stored as a messages record. The mobile chat UI reads these in real time.
FieldTypeDescription
sessionIdIDReference to the parent session
roleuser | assistantWho sent this message
contentstringText content of the message
editsobjectFile path, old string, new string (for edit operations)
bashobjectCommand, output, and exit code (for bash operations)
readobjectFile path (for file read operations)
todosarrayTask list items with status and priority
costUSDnumberAPI cost for this message
modelUsedstringModel identifier (e.g., claude-sonnet-4-20250514)

Session status lifecycle

A session advances through the following statuses as the sandbox is created and the agent runs. All transitions are written to Convex and stream to the mobile app in real time.
IN_PROGRESS


CLONING_REPO


INSTALLING_DEPENDENCIES


STARTING_DEV_SERVER


CREATING_TUNNEL


RUNNING


CUSTOM  ← AI agent is actively working
The CUSTOM status is used when the agent sends a status message of its own (for example, “Building the authentication flow”). Additional statuses (CREATING_GITHUB_REPO, PUSHING_TO_GITHUB, PUSH_COMPLETE) are used during the optional GitHub push flow.

Project structure

vibra-code/
├── vibracode-backend/            # Next.js 15 + Convex + Inngest
│   ├── app/api/                  # API routes (create-session, run-agent, webhooks)
│   ├── convex/                   # Database schema & query/mutation functions
│   ├── lib/inngest/functions/    # Background jobs
│   ├── lib/e2b/                  # Sandbox configuration
│   ├── lib/prompts.ts            # AI system prompts
│   └── e2b-cursor-template/      # E2B Dockerfile for the sandbox image

├── vibracode-mobile/             # React Native / Expo
│   └── apps/expo-go/
│       ├── src/screens/          # Vibra Code screens (VibraCreateAppScreen, etc.)
│       ├── src/services/         # VibraSessionService, VibraNotificationService
│       └── ios/Client/Menu/      # Native chat UI (Texture + IGListKit)

└── expo-template/                # Sandbox app template (Git submodule)
Ready to set up your own instance? Follow the quick start to get the backend and mobile app running end to end.

Build docs developers (and LLMs) love