Cloud Builds
Build your React Native app in the cloud, straight from the CLI — no Mac,
no CI pipeline, no local toolchain. Cloud builds are in beta: run
vibeview build --cloud and VibeView compiles a simulator/emulator build of
your app and drops it into your app’s Build History, ready to run on a cloud
device.
Cloud builds produce simulator and emulator builds for ios, android,
tvos, and androidtv, ready to run on a cloud device. Add --production
for a signed release build instead (ios, android, tvos, and
androidtv) — see
App Signing & Production Builds — and once a production
build succeeds, vibeview submit can upload it to TestFlight or a Google
Play track for you: see Store Submission. Roku
channels cannot be cloud-built — upload those as usual.
Configure your project
Cloud builds use the same vibeview.json build block that vibeview dev --build and local vibeview build use. Each platform entry needs a
build.command (the shell command that produces your build) and a
build.artifact (the project-relative path of the result; * is allowed in
the file name).
If a platform has no build block yet, vibeview build --cloud asks for both
values and saves them to vibeview.json straight away, so a failed build
never costs you the answers. Under --json or in a non-interactive shell it
reports the missing config as an error instead of prompting.
Install your dependencies as part of the build command
Your build runs in a clean environment that has only your source. Dependency
directories are not uploaded — node_modules, ios/Pods and .git are
always excluded, because they are large, machine-specific, and reproducible
from your lockfile. Nothing installs them for you, so your build command has
to do it:
{
"build": {
"command": "yarn install --immutable && yarn build:android",
"artifact": "android/app/build/outputs/apk/release/*.apk"
}
}
Use whatever your project already uses — yarn install --immutable,
npm ci, pnpm install --frozen-lockfile — and add pod install for a
native iOS build. A command that skips this step fails early with an error
like Couldn't find the node_modules state file or Cannot find module,
which means the dependencies were never installed rather than anything wrong
with your project.
If installing needs a private registry token, store it as a build secret rather than putting it in the command — see Build Variables & Secrets.
Expo managed projects
A managed Expo project — one with no ios/ or android/ directory — needs
no extra setup. The suggested build commands generate the native project
during the build itself: the production defaults run npx expo prebuild as
part of your build command, and the simulator defaults
(npx expo run:ios / npx expo run:android) prebuild automatically when
the native project is missing. Keep the generated ios/ and android/
directories out of git — prebuild recreates them on every build.
For a production iOS build, the suggested command derives the Xcode
workspace and scheme from the name in your app.json. If your project
uses a dynamic config (app.config.js / app.config.ts), that name can’t
be read without running your code, so no command is suggested — write your
build command by hand instead.
You do not need an existing app. If your project has never had a build
uploaded, the finished build creates the app for you — its name, package
identifier, platform and icon all come from the build itself, so nothing to
type and nothing to get wrong. When you already have apps for that platform,
vibeview build --cloud asks which one these builds should attach to, with
“Create a new app from this build” offered alongside. Either way the answer is
saved to vibeview.json as appId, so later builds go to the same app.
{
"defaultPlatform": "ios",
"platforms": {
"ios": {
"appId": "app_abc123",
"build": {
"command": "npx expo run:ios --configuration Debug --no-install",
"artifact": "ios/build/Build/Products/Debug-iphonesimulator/*.app",
"env": { "APP_VARIANT": "development" }
}
},
"android": {
"appId": "app_abc123",
"build": {
"command": "cd android && ./gradlew assembleDebug",
"artifact": "android/app/build/outputs/apk/debug/app-debug.apk"
}
}
}
}
Build environment variables
The optional build.env map sets plain environment variables for the build
command — useful for non-secret configuration like APP_VARIANT. Keys must
be valid environment variable names (letters, digits, underscores; not
starting with a digit). Treat build.env values like the rest of your
vibeview.json: they travel with your build request in plain text and are
visible to anyone in your organization, so it’s a good place for a build
flavor or feature flag, not an API key or credential.
For credentials, tokens, service-account files, and signing material, use
build variables and secrets instead — see
Build Variables & Secrets for how to store them, the
three visibility levels, and how to upload a file (such as a keystore or a
service-account JSON). If a stored variable has the same name as an entry in
build.env, the stored variable wins for that build.
Your project’s .env files follow the same rule as the rest of your source:
anything ignored by .gitignore is not uploaded.
Start a build
vibeview build --cloud # defaultPlatform
vibeview build --cloud --platform android
vibeview build --cloud --platform all # every configured platform with a build block
The CLI packs your project source — every file git tracks plus untracked
files that are not ignored by .gitignore — uploads it, and streams the
build log until the build finishes. Anything .gitignore matches stays on
your machine, but an untracked file that is not gitignored (a stray
credentials file, for example) is uploaded, so make sure secret files
are covered by .gitignore. Add a .vvignore file (same syntax as
.gitignore) to exclude additional paths from the upload. node_modules/,
ios/Pods/, and .git/ are always excluded, and the packed source may not
exceed 2 GB. Each build runs in a clean, isolated environment that is
destroyed when the build ends.
Useful flags:
| Flag | Effect |
|---|---|
--no-wait | Print the build ids and exit instead of streaming logs. |
--download | After a build succeeds, download its artifact to the current directory (implies waiting). |
--json | Emit NDJSON events (build_created, status, build_log, build_finished, artifact_saved, skipped, error) instead of human output. |
A status event reports a build’s progress before its log starts: once with
status: "queued" if the build is waiting for a build slot, and once with
status: "running" when it starts. A skipped event (with platform and
reason) is emitted only by --platform all --production, for each
configured platform that can’t be production-signed — those platforms are
left out while the rest still build.
Exit code is 0 when every requested build succeeds, 1 otherwise —
including when a --download fails.
Manage builds
vibeview builds list # recent cloud builds in your organization
vibeview builds logs <id> # print a build's log (exit 0 always)
vibeview builds logs <id> --follow # stream until done; exit 0 only if it succeeded
vibeview builds download <id> [--out d] # download a succeeded build's artifact
vibeview builds cancel <id> # cancel a queued or running build
vibeview builds delete-artifact <id> # delete a production build's stored artifact file
delete-artifact is irreversible — the artifact can’t be regenerated without
running a new build — but the build’s record, logs, and cost stay intact;
only the downloadable file is removed.
The Builds page
The Builds page in the dashboard has four tabs:
- Activity (the default) — every cloud build in your organization, with status, logs, and the Download/Delete actions for production artifacts. When a build fails because of a signing credential (missing or expired), its error shows a Fix in Signing link that jumps straight to the Signing tab.
- Signing — the signing credentials your production builds use: view, upload, rotate, and delete them. See App Signing & Production Builds.
- Variables — the build variables and secrets injected into your cloud builds (see below).
- Webhooks — notify your own systems the moment a build finishes. See Build Webhooks.
Managing build variables in the dashboard
The Variables tab shows every stored build variable — name, visibility, scope, and when it was last updated — and lets you add, edit, and delete them without the CLI. Any member of your organization can view the list; adding, editing, and deleting require the Admin role.
Adding or editing a variable works like vibeview env set: choose a name,
a value (or upload a file), a visibility level, and a scope (org-wide or a
specific app). See Build Variables & Secrets for
what the visibility levels mean and the limits that apply.
The tab never lists full values back: at most the last 4 characters of a plain or sensitive value are shown, and secrets and files show nothing at all. A secret can only be replaced with a new value, never viewed; a file variable can’t be edited in place — delete it and add it again.
Precedence is the same everywhere: an app-scoped variable overrides an
org-wide variable of the same name, and both override a build.env entry
of the same name in vibeview.json. Each app’s Build Settings tab
shows the effective set that reaches that app’s builds after this merge,
alongside a preview of what its production builds would sign with.
Production builds
Add --production to build a signed release artifact instead of a
simulator/emulator build:
vibeview build --cloud --production
Production builds are supported for ios, android, tvos, and
androidtv. Android TV release builds sign with your Android credential —
one keystore covers both form factors. tvOS builds sign with a tvOS
credential (the same Apple distribution certificate, paired with a tvOS
provisioning profile) — see
App Signing & Production Builds.
This needs a signing credential uploaded first, and behaves differently from
a regular cloud build in one important way: the artifact is downloaded,
not installed. It does not appear in Build History and can’t be run on a
device in VibeView. See App Signing & Production Builds
for uploading credentials, expiry, and the Android build.gradle change.
Automatic build numbers
Apple and Google both refuse an upload that reuses a build number, and a
forgotten bump costs a full rebuild. VibeView can manage the number for
you: set autoIncrement in the platform’s build block, and every
production build for that app gets the next number in a per-app,
per-platform counter that VibeView keeps for you:
{
"platforms": {
"ios": {
"appId": "my-app-abc123",
"build": { "...": "...", "autoIncrement": true }
}
}
}
The assigned number reaches your build as the VIBEVIEW_BUILD_NUMBER
environment variable — wire it into your project once:
// Expo: app.config.js / app.config.ts
ios: { buildNumber: process.env.VIBEVIEW_BUILD_NUMBER },
android: { versionCode: parseInt(process.env.VIBEVIEW_BUILD_NUMBER ?? '1', 10) },
// Bare React Native: android/app/build.gradle
versionCode (System.getenv("VIBEVIEW_BUILD_NUMBER") ?: "1").toInteger()
autoIncrement needs the platform linked to an app (appId) and applies
to production builds only. For an app that already has builds in a store,
seed the counter once so the next number lands above what’s out there:
vibeview versions list --app my-app-abc123
vibeview versions set --app my-app-abc123 --platform ios 42
For iOS and tvOS there’s a shortcut: when your organization has an App
Store Connect key stored, the very first allocation checks your app’s
highest existing build number and starts above it automatically — no
seeding needed. The check covers your app’s 200 most recent uploads:
for an app with a longer history whose highest build number is older than
that, seed the counter once with vibeview versions set instead. If the
lookup isn’t possible, the counter simply starts at 1.
Artifacts and Build History
A succeeded regular (non-production) cloud build registers automatically as
a build of the configured app — it appears in the app’s Build History
tab in the dashboard with a cloud badge, exactly like an uploaded build:
you can run it on a device, share it, and use it with vibeview dev.
Builds can be downloaded from the dashboard (Download button) or with
vibeview builds download.
While a cloud build is queued or running — or if it finished without succeeding — it appears above the Build History list with its status and log. Unsuccessful builds stay visible there for a day.
A production build follows a different path: it shows up on the Builds page (not the app’s Build History) with a Download action once it succeeds — see App Signing & Production Builds.
Billing and limits
Each platform build is billed individually from your organization’s usage credit once it finishes. Your plan includes a monthly allowance of builds at no charge; builds beyond it draw from usage credit. You are not charged for builds canceled while still queued, or for builds that fail for reasons on our side.
Builds time out after 45 minutes on the Free plan and 2 hours on paid plans. One build runs at a time on Free, Dev, and Starter; two on Pro (additional builds queue). For custom terms, contact support@vibeview.io.
You can track your build usage under Settings → Usage — builds run this month, how much of your free allowance is used, and build spend. Charged builds appear in the Settings → Credits cost history labeled “Cloud build”.
While a build is waiting for a free slot, the CLI shows
queued — waiting for a build slot and the dashboard shows a queued
badge; the build’s time limit only starts counting once it actually starts.
If no build capacity is available for an extended period, the build fails
with a clear error instead of waiting forever — you are not charged and
your free allowance is not consumed.