A Capacitor app is a web app inside two native projects, so one build is three jobs: build the web app, copy it into ios/ and android/ with cap sync, then compile each native project with its own toolchain. That last step is the one that ties you to a Mac for iOS and to Android Studio for Android. VibeView cloud builds run all three for you. The CLI uploads your project source, the build runs in a clean environment, and the finished build lands next to your app, ready to run on a device you open in a browser tab.
This guide takes one Capacitor app from source to running builds on both platforms, then to a signed Android release. It works the same for Ionic apps that use Capacitor, and from Windows, Linux or macOS.
What you need
- A VibeView account and the CLI:
npm install -g vibeview && vibeview login. CLI 0.42.0 or later suggests the Capacitor commands; on an older CLI, type them in when it asks. - A Capacitor project with its
ios/andandroid/folders committed (the onesnpx cap add iosandnpx cap add androidcreate). The build syncs your web app into them but doesn’t create them.
You don’t need Xcode, CocoaPods, the Android SDK or a JDK locally. Every plan includes cloud builds each month; builds beyond your plan’s allowance draw from usage credit. The pricing page has each plan’s numbers.
Part 1: debug builds on cloud devices
-
Start the builds from your project root.
vibeview build --cloud --platform allThe first run asks for each platform’s build command and where the result lands, and saves the answers to
vibeview.json. For a Capacitor 8 project with apackage-lock.jsonthe CLI suggests:{ "defaultPlatform": "android", "platforms": { "android": { "build": { "command": "npm ci && npm run build && npx cap sync android && cd android && JAVA_HOME=${JAVA_HOME_21:-$JAVA_HOME} ./gradlew assembleDebug", "artifact": "android/app/build/outputs/apk/debug/*.apk" } }, "ios": { "build": { "command": "npm ci && npm run build && npx cap sync ios && xcodebuild -project ios/App/App.xcodeproj -scheme App -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build CODE_SIGNING_ALLOWED=NO", "artifact": "ios/build/Build/Products/Debug-iphonesimulator/*.app" } } } }The install step follows your lockfile (
npm ci,yarn install --immutableorpnpm install --frozen-lockfile), becausenode_modulesis never uploaded. The web build runs yourbuildscript, whatever framework it uses, and is left out whenpackage.jsonhas none. -
Watch the logs. The CLI packs every file git tracks plus untracked files that
.gitignoredoesn’t exclude, uploads them, and streams each build’s output. Add--no-waitto start the builds and leave;vibeview builds logs <id> --followpicks one back up. -
Run them. A succeeded build lands in the app’s Build history with a
cloudbadge. If the project had no app yet, the build creates one from the binary (name, bundle id and icon included) and the CLI writes itsappIdintovibeview.json. Open the build’s page and choose Run this build to start it on a cloud iPhone or Android emulator.
You’ll know it worked when the build page shows added to app builds on its timeline and your web app opens inside the native shell on the device. The web assets are bundled into the build, so it runs on its own: share it as a link, record tests on it, or let your coding agent tap through it.
Why the Android command sets JAVA_HOME
Capacitor 7 and later compile their Android library for Java 21, and they ask for it directly rather than through a Gradle toolchain. On the default Java 17 the build stops with invalid source release: 21. The cloud builders have both Java versions and set JAVA_HOME_21, so the suggested command runs Gradle on Java 21. The :-$JAVA_HOME part leaves a local vibeview build on your machine’s own Java. The CLI adds the part when your Gradle wrapper is 8.5 or later, as Capacitor 7 and later ship; Capacitor 6’s older Gradle can’t run on Java 21, so its suggestion leaves the part out. After a Capacitor upgrade, add it to the saved command in vibeview.json yourself, or the build fails with the same error and says which line to add.
Older projects that use CocoaPods
Capacitor 8 projects use Swift Package Manager, so the iOS command builds ios/App/App.xcodeproj directly. A project with a Podfile in ios/App, the CocoaPods setup of earlier Capacitor versions, builds the workspace instead: the CLI sees the Podfile and suggests -workspace ios/App/App.xcworkspace. npx cap sync ios runs pod install, and the cloud builders have CocoaPods.
Part 2: a signed .aab for Google Play
The release is a signed .aab for the store, not a build that runs on a VibeView device, so it lands on the Builds page with a Download action. The Capacitor-specific part is that the same install, web build and sync run first.
-
Get a keystore. Upload the one you have with
vibeview credentials add --platform android --file release.jks, or let VibeView make one withvibeview credentials generate --platform android --name release. -
Point Gradle at it. Add the signing block from App Signing to
android/app/build.gradle. VibeView sets the four properties it reads only during a production build, so your local builds keep working as before. -
Build the release.
vibeview build --cloud --production --platform androidThe first run offers the same install, web build and sync, then
./gradlew bundleRelease, with the artifact atandroid/app/build/outputs/bundle/release/*.aab. Thenvibeview submit --platform android --latest --track internaluploads it to Google Play; the Android cloud build guide covers the one-time Play Console setup.
For iOS, a production build is your own archive command signed with your Apple credentials: see App Signing.
Troubleshooting
invalid source release: 21. Gradle ran on Java 17. Run it withJAVA_HOME=${JAVA_HOME_21:-$JAVA_HOME}as in the suggested command.Cannot find moduleor a missingnode_moduleserror. The build command didn’t install dependencies. Add your install step to the front of it.- The app opens on a blank or old screen. The command skipped the web build or
cap sync, so the native project carries whatever web assets were last committed. Keep both legs in the command. - The CLI suggests no iOS command. It couldn’t find
ios/App/App.xcodeprojwith one scheme. Commit theios/folder, or enter your ownxcodebuildcommand.
Frequently asked questions
Frequently asked questions
Does this work for Ionic apps?
Yes, if it uses Capacitor, which new Ionic apps do. The CLI finds the capacitor.config file and suggests the same commands, with your Ionic build as the web build step. An older Ionic app on Cordova isn’t a Capacitor project, so write its build command yourself.
Can I build a Capacitor iOS app without a Mac?
Yes. The iOS cloud build runs on a macOS builder with Xcode and CocoaPods, and the simulator build it makes opens on a cloud iPhone in your browser. You still need an Apple Developer account to sign and publish a production build.
Can I build for Apple TV or Android TV?
Capacitor doesn’t support Apple TV. The CLI doesn’t suggest an Android TV development build command, so enter your own when it asks.
Next steps
- Capacitor and Ionic cloud builds: what the builders have, what it costs and what it doesn’t do
- Ionic Appflow alternative: moving your builds off Appflow
- Cloud Builds, App Signing and Store Submission: the reference docs
- Build a React Native Android app in the cloud: Google Play setup and submission in more depth
- Build a Flutter iOS and Android app without a Mac: the same path for Flutter