Native iOS chat system
The chat UI in Vibra Code is not a React Native component. It is a fully native iOS interface built with Texture (AsyncDisplayKit) and IGListKit, rendering off the main thread at a consistent 60fps regardless of how many messages are in the session. The entire system lives inapps/expo-go/ios/Client/Menu/. The coordinator for the experience is a singleton called EXPreviewZoomManager.
Core files
| File | Purpose |
|---|---|
EXPreviewZoomManager.h/m | Main singleton — coordinates zoom, chat, bars, and the entire preview experience |
EXPreviewZoomManager+Zoom.m | Zoom in/out animations (3D transform with perspective) |
EXPreviewZoomManager+ChatView.m | Chat UI, message rendering, session loading from Convex |
EXPreviewZoomManager+TopBar.m | Top bar — app name, refresh button, chevron, three-dots menu |
EXPreviewZoomManager+BottomBar.m | Bottom bar — text input, send, mic (voice), image attach, model selector |
EXPreviewZoomManager+Keyboard.m | Keyboard show/hide handling and layout constraints |
EXPreviewZoomManager+Gestures.m | Tap gestures for zoom/chat toggle |
EXPreviewZoomManager+WebPreview.m | Web project preview (WKWebView for non-mobile projects) |
Chat components (Chat/)
| File | Purpose |
|---|---|
EXChatListAdapter.h/m | IGListKit + Texture adapter — O(N) diffing for efficient list updates |
EXChatMessageNode.h/m | ASCellNode for user/assistant text messages with markdown |
EXChatGroupNode.h/m | ASCellNode for tool operations — file reads (blue), edits (orange), bash (green) |
EXChatTaskCardNode.h/m | ASCellNode for todo task cards with Liquid Glass effect |
EXChatStatusNode.h/m | ”Working…” status indicator with shimmer animation |
EXChatMessageCache.h/m | Message caching for offline support |
EXLottieAnimationHelper.swift | Cell animations (springIn, fadeIn, shimmer, glass effects) |
EXMarkdownHelper.swift | Markdown parsing (bold, italic, code blocks, links) |
Message types
Messages from Convex carry arole and optional tool fields. The chat renderer selects a node type based on which field is populated:
| Message type | Node class | Visual style |
|---|---|---|
message (user/assistant text) | EXChatMessageNode | Plain text with markdown rendering |
read (file read operation) | EXChatGroupNode | Blue accent |
edit (file edit operation) | EXChatGroupNode | Orange accent |
bash (terminal command) | EXChatGroupNode | Green accent |
tasks (todo list) | EXChatTaskCardNode | Liquid Glass card |
status (working indicator) | EXChatStatusNode | Shimmer animation |
Animation system
EXLottieAnimationHelper.swift provides three helpers used across cell nodes:
EXCellAnimationHelper— cell appear animations:springIn,fadeIn,slideUp,scaleInEXTextShimmerHelper— text shimmer effect used on the “Working…” status nodeEXGlassEffectHelper— iOS 26 Liquid Glass materials with a pre-iOS 26 fallback
UIView.animate(springDuration:) rather than CAAnimation directly, keeping them compatible with iOS 26+ spring curves.
Services
| File | Purpose |
|---|---|
EXChatBackendService.h/m | API calls to the Convex backend — send messages, load sessions |
EXAudioRecorderService.h/m | Voice recording via AVFoundation |
EXAssemblyAIService.h/m | Sends recorded audio to AssemblyAI for transcription |
EXWebPreviewView.h/m | WKWebView wrapper for web project previews |
Convex schema design
All persistent state in Vibra Code lives in Convex (vibracode-backend/convex/schema.ts). The schema is shared between the backend and the mobile app via a symlink, so both sides always use the same type definitions.
Table overview
| Table | Purpose |
|---|---|
users | One row per Clerk user. Stores profile, subscription plan, billing mode (tokens vs. credits), credit balances, and push notification tokens. |
sessions | One row per build session. Tracks the sandbox ID, tunnel URL, template, current status, message count, and total cost. |
messages | One row per chat message. Supports text content plus structured fields for every tool the AI agent can use: edits, bash, read, todos, webSearch, mcpTool, codebaseSearch, grep, searchReplace. Also stores images, audio, and video attachments. |
paymentTransactions | Audit log of every Stripe and RevenueCat transaction: payments, refunds, chargebacks, plan changes. |
globalConfig | Key-value pairs for admin-controlled settings (e.g., global agentType override). |
convexProjectCredentials | Stores Convex OAuth tokens for users who connect their own Convex project. |
githubCredentials | GitHub OAuth access tokens per user, used by the push-to-GitHub feature. |
revenuecatCredentials | RevenueCat OAuth tokens for the RevenueCat MCP integration. |
generatedImages | Records of every AI-generated or user-uploaded image in the Image Studio. |
generatedAudios | Records of every AI-generated audio file in the Audio Studio. |
generatedVideos | Records of every AI-generated video file in the Video Studio. |
stolenApps | Research data from the App Stealer feature — scraped app metadata used to seed AI generation. |
Session status state machine
A session moves through a defined sequence of statuses as the sandbox is provisioned and the agent runs. The mobile app displays a human-readable label for each status.INSTALLING_DEPENDENCIES
Package manager running (e.g.,
npm install). Maps to startCommands entries with status: "INSTALLING_DEPENDENCIES".STARTING_DEV_SERVER
Dev server starting. Maps to
startCommands entries with status: "STARTING_DEV_SERVER".CREATING_GITHUB_REPO, SETTING_UP_SANDBOX, INITIALIZING_GIT, ADDING_FILES, COMMITTING_CHANGES, PUSHING_TO_GITHUB, PUSH_COMPLETE, and PUSH_FAILED.
Inngest background jobs
Inngest handles all long-running work that cannot block an API request. The functions live invibracode-backend/lib/inngest/functions/.
create-session.ts
Triggered when a user starts a new build. Responsibilities:
- Create the E2B sandbox using the template’s
imageID (or the default image) - Clone the template repository into the sandbox
- Run each
startCommandin order, updating the session status as each completes - Create the E2B tunnel and write the
tunnelUrlto the Convex session record - Trigger the
run-agentfunction
run-agent.ts
Runs the AI agent inside the sandbox. Responsibilities:
- Load the system prompt for the template (resolving
FILE:references if needed) - Build the message history from the Convex
messagestable - Start the configured agent (
claude,cursor, orgemini) with the system prompt and message history - Stream tool use events (file reads, edits, bash commands, todo updates) to Convex in real time
- Track token usage and compute cost, writing
costUSDto each message andtotalCostUSDto the session - Set session status back to
RUNNINGwhen the agent finishes
push-to-github.ts
Triggered when a user taps the publish button. Responsibilities:
- Retrieve the user’s GitHub OAuth token from
githubCredentials - Create a new repository on the user’s GitHub account (or reuse an existing one)
- Inside the sandbox: initialize git, add all files, commit, and push
- Update the session with
githubRepository,githubRepositoryUrl, andgithubPushStatus
E2B sandbox lifecycle
Each build session gets a dedicated, isolated E2B cloud sandbox. The sandbox is ephemeral — it exists only for the duration of the session.Create sandbox
The
create-session Inngest function calls the E2B API to create a new sandbox from the template’s image ID. If no image is specified, E2B uses its default base image.Clone template repository
The sandbox runs
git clone <repository> to fetch the starter project from GitHub. The session status is set to CLONING_REPO.Install dependencies
Each
startCommand with status: "INSTALLING_DEPENDENCIES" runs in sequence (blocking). The session status updates to INSTALLING_DEPENDENCIES while these run.Start dev server
Each
startCommand with status: "STARTING_DEV_SERVER" and background: true launches the dev server as a background process. The session status updates to STARTING_DEV_SERVER.Create tunnel
E2B creates a public HTTPS tunnel to the dev server port (3000). The
tunnelUrl is written to the Convex session record. The session status becomes CREATING_TUNNEL then RUNNING.Run AI agent
The
run-agent Inngest function starts the AI agent inside the sandbox. The agent reads and edits files, runs bash commands, and streams updates to Convex. Session status is set to CUSTOM with the agent’s current task as the status message.