Getting Started¶
In this guide, you will set up Capawesome Cloud Live Updates in your app and ship your first over-the-air update. The Live Update SDK is available for both Capacitor and Cordova with full API parity — use the runtime tabs throughout this guide to follow along with your framework.
Prefer to learn from a working example?
Clone a ready-to-run demo app with Live Updates already wired up:
Prerequisites¶
Before you begin, ensure you have:
- A Capawesome Cloud account and organization.
- A Capacitor or Cordova app project on your local machine.
- The latest version of the Capawesome CLI installed and authenticated.
AI-Assisted Setup (Recommended)¶
The fastest way to get started is with an AI coding assistant. First, add the Capawesome skills to your project:
Then use the following prompt in your preferred AI tool (e.g. Claude Code, Cursor, or GitHub Copilot):
Use the `capawesome-cloud` skill from `capawesome-team/skills` to help me set up Live Updates in my project.
The assistant will create an app in Capawesome Cloud, install and configure the SDK, publish your first update, and verify that everything works. Once complete, continue with Next Steps.
Manual Setup¶
If you prefer to set things up manually, follow the steps below.
Step 1: Create an App¶
To identify your app to Capawesome Cloud, first create an app. If you already have one, skip to Step 2.
Use the apps:create command:
You will be prompted to select an organization and provide a name. The CLI then creates the app and prints the app ID.
Open the Capawesome Cloud Console, select your organization, and click Create App. Provide a name and click Create.
Copy the app ID — you will need it in the next step.
Step 2: Install the SDK¶
Install the Live Update SDK in your project.
Older Capacitor versions
For Capacitor 7, use @capawesome/capacitor-live-update@v7-lts. For Capacitor 6, use @capawesome/capacitor-live-update@v6-lts.
cordova plugin add @capawesome/cordova-live-update --variable APP_ID=00000000-0000-0000-0000-000000000000
Replace the APP_ID value with the app ID from Step 1.
WebView scheme
The plugin requires the default custom WebView scheme. It does not work if your app sets Scheme=file or AndroidInsecureFileModeEnabled=true.
Step 3: Configure the SDK¶
Configure the SDK with your app ID and the recommended settings. The autoUpdateStrategy: background option checks for updates on app start and resume, downloads them in the background, and applies them on the next launch — no extra code required. The readyTimeout and autoBlockRolledBackBundles options enable automatic rollback of a broken update.
import { CapacitorConfig } from "@capacitor/cli";
const config: CapacitorConfig = {
plugins: {
LiveUpdate: {
appId: "00000000-0000-0000-0000-000000000000",
autoUpdateStrategy: "background",
autoBlockRolledBackBundles: true,
readyTimeout: 10000
}
}
};
export default config;
Apply the configuration:
Configure the plugin via preferences in your config.xml:
<preference name="APP_ID" value="00000000-0000-0000-0000-000000000000" />
<preference name="AUTO_UPDATE_STRATEGY" value="background" />
<preference name="AUTO_BLOCK_ROLLED_BACK_BUNDLES" value="true" />
<preference name="READY_TIMEOUT" value="10000" />
Cordova only reads these preferences when a platform is added, so changes to them don't take effect until you remove and re-add the affected platforms:
For automatic rollback to work, call ready() as early as possible at app start to signal that the new bundle started successfully:
Step 4: Publish Your First Update¶
Build your web assets, then upload them as a Live Update bundle with the CLI (the same command for both runtimes):
You will be prompted for the path to your web assets directory (e.g. www or dist) and the target app. After the upload completes, the bundle is available to your users. Open the Deployments page in the Console to see the details.
Step 5: Test Your Setup¶
Make a small visible change to your web assets, rebuild, and upload a new bundle with the same command. Then force-close and restart your app.
Force an update check
With an autoUpdateStrategy, updates are only checked on resume if the last check was more than 15 minutes ago. During development, force-close and restart the app to trigger a check immediately.
Wait around 15–30 seconds, then restart again to see the change take effect. 🎉
Not seeing the update? Head over to Troubleshooting — it walks through the most common reasons an update doesn't reach the device and how to fix them.
Make Updates Version-Compatible¶
Do this before shipping to production
A Live Update can only change your web layer — it must stay compatible with the native binary already installed on the device. Shipping a bundle that relies on a native feature an older app version doesn't have will crash the app on launch. See Binary-Compatible Changes for the full rules.
The safest way to prevent this is versioned channels: pin each native release to its own channel so a bundle only ever reaches compatible devices. Configure the channel natively at build time, derived from your version code.
On Android, add a resource value in android/app/build.gradle:
android {
defaultConfig {
resValue "string", "capawesome_live_update_default_channel",
"production-" + defaultConfig.versionCode
}
}
On iOS, add a key to ios/App/App/Info.plist:
On Android, set the channel via a build-extras.gradle file included through your config.xml:
android {
applicationVariants.all { variant ->
variant.resValue "string", "capawesome_live_update_default_channel",
"production-" + variant.versionCode
}
}
On iOS, add the channel key to your Info.plist via config.xml:
Every native release now ships pinned to its own channel, and uploads to production-<version> only reach matching devices. See Manage Channels for alternatives, such as selecting the channel at runtime.
Next Steps¶
-
Publish an Update
The recurring workflow for shipping updates to your users.
-
Sign Your Bundles
Add code signing so only you can publish updates to your app.
Bonus: Video Walkthrough¶
Prefer to watch the setup end-to-end? This walkthrough covers the first deployment, channel setup, and runtime behavior in a real project: