skills/ionic-appflow-migration/SKILL.md
Guides the agent through migrating an existing Ionic/Capacitor project from Ionic Appflow to Capawesome Cloud. Detects which Appflow features are in use (Live Updates, Native Builds, App Store Publishing) and provides step-by-step migration for each feature to its Capawesome Cloud equivalent. Covers SDK replacement, configuration mapping, API migration, CI/CD pipeline updates, and verification. References the capawesome-cloud skill for detailed Capawesome Cloud setup procedures. Do not use for setting up Capawesome Cloud from scratch without an existing Appflow project, for non-Capacitor mobile frameworks, or for migrating Ionic Enterprise plugins.
npx skillsauth add capawesome-team/skills ionic-appflow-migrationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Migrate an existing Ionic/Capacitor project from Ionic Appflow to Capawesome Cloud.
@capawesome/cli command for the first time, run it with the --help flag to review all available options.package.json (@capacitor/core) before making any changes — it affects which plugin version and update strategy to use.Scan the project to determine which Appflow features are in use.
Search for these signals:
@capacitor/live-updates in package.json (dependencies or devDependencies).cordova-plugin-ionic in package.json — this is the legacy Cordova SDK for Ionic Live Updates.LiveUpdates key inside the plugins object in capacitor.config.ts or capacitor.config.json.@capacitor/live-updates or cordova-plugin-ionic in TypeScript/JavaScript source files.If any signal is found, mark Live Updates as in use. Also record which SDK is in use (@capacitor/live-updates or cordova-plugin-ionic).
Record the current configuration values:
appId (Ionic Appflow app ID)autoUpdateMethod (background, always, or none)channelenabledmaxVersionsSearch for these signals:
ionic appflow build in CI/CD configuration files (e.g., .github/workflows/*.yml, .gitlab-ci.yml, bitrise.yml, Jenkinsfile, azure-pipelines.yml).dashboard.ionicframework.com or appflow.ionic.io in CI/CD files or scripts.appflow.config.json or similar Appflow build configuration file in the project root.If any signal is found, mark Native Builds as in use.
Search for these signals:
ionic appflow deploy in CI/CD configuration files.If any signal is found, mark App Store Publishing as in use.
Present the detected features to the user. Ask the user to confirm which features to migrate. The user may choose to migrate all detected features or only a subset.
npx @capawesome/cli login
Skip if the user already has a Capawesome Cloud app ID.
npx @capawesome/cli apps:create
Save the returned app ID (UUID) for subsequent steps.
Skip this step if Live Updates was not detected or the user chose not to migrate it.
If the project uses @capacitor/live-updates:
npm uninstall @capacitor/live-updates
If the project uses the legacy Cordova SDK (cordova-plugin-ionic):
npm uninstall cordova-plugin-ionic
Read references/cordova-sdk-migration.md for the native configuration cleanup steps (removing legacy keys from Info.plist, strings.xml, and Capacitor config).
Install the version matching the project's Capacitor version:
npm install @capawesome/capacitor-live-update@latestnpm install @capawesome/capacitor-live-update@^7.3.0npm install @capawesome/capacitor-live-update@^6.0.0Replace the LiveUpdates plugin config with LiveUpdate in capacitor.config.ts (or .json). Map the configuration options as follows:
| Ionic Appflow (LiveUpdates) | Capawesome Cloud (LiveUpdate) | Notes |
|---|---|---|
| appId | appId | Replace with the Capawesome Cloud app ID from Step 2 |
| autoUpdateMethod: 'background' | autoUpdateStrategy: 'background' | Capacitor 7/8 only. Omit for Capacitor 6 |
| autoUpdateMethod: 'always' | autoUpdateStrategy: 'background' | Capacitor 7/8 only. Also add nextBundleSet listener (see Step 3.5) |
| autoUpdateMethod: 'none' | (omit autoUpdateStrategy) | Use manual sync code instead (see Step 3.6) |
| channel | defaultChannel | Same value |
| enabled | (remove) | Not needed — controlled in code |
| maxVersions | autoDeleteBundles: true | Boolean instead of number |
Example — Capacitor 7/8 with background strategy:
// capacitor.config.ts
const config: CapacitorConfig = {
plugins: {
- LiveUpdates: {
- appId: 'abc12345',
- autoUpdateMethod: 'background',
- channel: 'production',
- maxVersions: 3
- }
+ LiveUpdate: {
+ appId: '<CAPAWESOME_APP_ID>',
+ autoUpdateStrategy: 'background',
+ defaultChannel: 'production',
+ autoDeleteBundles: true
+ }
}
};
Example — Capacitor 6 (no autoUpdateStrategy):
// capacitor.config.ts
const config: CapacitorConfig = {
plugins: {
- LiveUpdates: {
- appId: 'abc12345',
- channel: 'production',
- maxVersions: 3
- }
+ LiveUpdate: {
+ appId: '<CAPAWESOME_APP_ID>',
+ defaultChannel: 'production',
+ autoDeleteBundles: true
+ }
}
};
Search all TypeScript/JavaScript files for imports of @capacitor/live-updates (or cordova-plugin-ionic) and replace. The Ionic SDK uses two import styles — replace both:
-import * as LiveUpdates from '@capacitor/live-updates';
+import { LiveUpdate } from '@capawesome/capacitor-live-update';
-import { LiveUpdates } from '@capacitor/live-updates';
+import { LiveUpdate } from '@capawesome/capacitor-live-update';
If the project uses the legacy Cordova SDK (cordova-plugin-ionic), read references/cordova-sdk-migration.md for the complete Deploy → LiveUpdate method mapping, including the granular check-download-extract-reload pattern and native config cleanup.
Replace all references to the LiveUpdates class (or Deploy class) with LiveUpdate (singular).
sync() return value has changed. The Ionic Capacitor SDK returns { activeApplicationPathChanged: boolean }. The Capawesome SDK returns { nextBundleId: string | null }. Update all code that checks the sync result:
const result = await LiveUpdate.sync();
-if (result.activeApplicationPathChanged) {
+if (result.nextBundleId) {
await LiveUpdate.reload();
}
reload() has the same signature — no changes needed beyond the class name.
setConfig(), getConfig(), and resetConfig() exist but have different signatures (Capacitor 7/8 only, since v7.4.0). The Capawesome SDK splits config and channel management into separate methods:
// Setting config at runtime
-await LiveUpdates.setConfig({ appId: '456', channel: 'staging', maxVersions: 5 });
+await LiveUpdate.setConfig({ appId: '456' });
+await LiveUpdate.setChannel({ channel: 'staging' });
// Getting config at runtime
-const config = await LiveUpdates.getConfig();
-console.log(config.channel);
+const config = await LiveUpdate.getConfig(); // { appId, autoUpdateStrategy }
+const { channel } = await LiveUpdate.getChannel(); // { channel }
// Resetting config
-await LiveUpdates.resetConfig();
+await LiveUpdate.resetConfig();
maxVersions has no runtime equivalent — use autoDeleteBundles: true in the static Capacitor config instead.
If the previous Ionic Appflow autoUpdateMethod was always, add a nextBundleSet listener to prompt the user when an update is ready. Add this code early in the app's initialization:
import { LiveUpdate } from '@capawesome/capacitor-live-update';
LiveUpdate.addListener('nextBundleSet', async (event) => {
if (event.bundleId) {
const shouldReload = confirm('A new update is available. Install now?');
if (shouldReload) {
await LiveUpdate.reload();
}
}
});
Copy this snippet exactly. Do not simplify or omit the confirm() dialog.
If the project implements a "Force Update" pattern (extending the splash screen until the update completes), migrate it as follows:
import { SplashScreen } from '@capacitor/splash-screen';
-import * as LiveUpdates from '@capacitor/live-updates';
+import { LiveUpdate } from '@capawesome/capacitor-live-update';
const initializeApp = async () => {
- const result = await LiveUpdates.sync();
- if (result.activeApplicationPathChanged) {
- await LiveUpdates.reload();
+ const { nextBundleId } = await LiveUpdate.sync();
+ if (nextBundleId) {
+ await LiveUpdate.reload();
} else {
await SplashScreen.hide();
}
};
This pattern may impact user experience on slow connections. Consider migrating to the background update strategy instead.
Capacitor 6 does not support autoUpdateStrategy. If the project uses Capacitor 6, add manual sync logic:
import { App } from '@capacitor/app';
import { LiveUpdate } from '@capawesome/capacitor-live-update';
void LiveUpdate.ready();
App.addListener('resume', async () => {
const { nextBundleId } = await LiveUpdate.sync();
if (nextBundleId) {
const shouldReload = confirm('A new update is available. Install now?');
if (shouldReload) {
await LiveUpdate.reload();
}
}
});
Add readyTimeout and autoBlockRolledBackBundles to the LiveUpdate config:
LiveUpdate: {
appId: '<CAPAWESOME_APP_ID>',
autoUpdateStrategy: 'background', // Capacitor 7/8 only
readyTimeout: 10000,
autoBlockRolledBackBundles: true,
}
Call ready() as early as possible in app startup:
import { LiveUpdate } from '@capawesome/capacitor-live-update';
void LiveUpdate.ready();
Add to ios/App/PrivacyInfo.xcprivacy inside the NSPrivacyAccessedAPITypes array:
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
npx cap sync
Skip this step if Native Builds was not detected or the user chose not to migrate it.
Native build setup in Capawesome Cloud requires connecting a Git repository, uploading signing certificates, configuring environments, and triggering builds. Use the capawesome-cloud skill — follow the Native Builds section starting from "Connect Git Repository." Specifically, read the capawesome-cloud skill's references/native-builds.md for the full procedure.
Remove any Ionic Appflow build commands from CI/CD configuration files after verifying that Capawesome Cloud builds work correctly (see Step 6 for CI/CD migration).
Skip this step if App Store Publishing was not detected or the user chose not to migrate it.
App store publishing setup requires creating destinations and configuring credentials for Apple App Store and/or Google Play Store. Use the capawesome-cloud skill — follow the App Store Publishing section. Specifically, read the capawesome-cloud skill's references/app-store-publishing.md for the full procedure.
Remove any Ionic Appflow deploy commands from CI/CD configuration files after verifying that Capawesome Cloud deployments work correctly (see Step 6 for CI/CD migration).
Skip this step if the project has no CI/CD pipeline or uses Ionic Appflow's built-in build/deploy features without external CI/CD.
Use the following CLI command mapping as a reference when replacing Appflow commands:
| Appflow CLI Command | Capawesome CLI Equivalent |
|---|---|
| appflow live-update upload-artifact | npx @capawesome/cli apps:liveupdates:upload |
| appflow live-update create-channel | npx @capawesome/cli apps:channels:create |
| appflow live-update delete-channel | npx @capawesome/cli apps:channels:delete |
| appflow live-update list-channels | npx @capawesome/cli apps:channels:list |
| appflow live-update download-artifact | npx @capawesome/cli apps:liveupdates:download |
| appflow live-update set-native-versions | Use versioned channels or --android-min/--ios-min flags on upload |
| appflow build | npx @capawesome/cli apps:builds:create |
| appflow deploy | npx @capawesome/cli apps:deployments:create |
Replace Ionic Appflow authentication with Capawesome Cloud token-based auth:
-# Ionic Appflow authentication
-IONIC_TOKEN: ${{ secrets.IONIC_TOKEN }}
+# Capawesome Cloud authentication
+- run: npx @capawesome/cli login --token ${{ secrets.CAPAWESOME_CLOUD_TOKEN }}
Generate a token in the Capawesome Cloud Console and store it as a CI/CD secret named CAPAWESOME_CLOUD_TOKEN.
-ionic appflow build android --type release
+npx @capawesome/cli apps:builds:create --app-id <APP_ID> --platform android --type release --git-ref main --certificate "<CERTIFICATE_NAME>" --yes
-ionic appflow build ios --type app-store
+npx @capawesome/cli apps:builds:create --app-id <APP_ID> --platform ios --type app-store --git-ref main --certificate "<CERTIFICATE_NAME>" --yes
Add --detached for non-blocking builds in CI/CD pipelines.
-ionic appflow deploy web --channel production
+npx @capawesome/cli apps:liveupdates:upload --app-id <APP_ID> --channel production
-ionic appflow deploy android --destination "Google Play"
+npx @capawesome/cli apps:deployments:create --app-id <APP_ID> --build-number <BUILD_NUMBER> --destination "<DESTINATION_NAME>"
After verifying the new CI/CD pipeline works:
@ionic/appflow or Appflow-related npm packages from package.json.IONIC_TOKEN).appflow.config.json or similar Appflow configuration files from the project root.Ask the user whether to test live update functionality. If accepted:
npm run build.npx @capawesome/cli apps:channels:list --app-id <APP_ID> --json
npx @capawesome/cli apps:channels:create --app-id <APP_ID> --name <CHANNEL_NAME>
npx @capawesome/cli apps:liveupdates:upload --app-id <APP_ID> --channel <CHANNEL_NAME>
npm run build && npx cap sync
npx cap open ios or npx cap open android) and run on a device or emulator.autoUpdateStrategy: "background", wait for the update prompt or force-close and reopen the app. For Capacitor 6, switch away from the app and return to trigger a check.Trigger a test build via the Capawesome CLI and verify the build artifact is produced.
Deploy a test build to the configured destination and verify it appears in TestFlight or Google Play Console.
After all features are verified:
package.json.capacitor.config.ts/capacitor.config.json.npm uninstall @capacitor/live-updates fails → The package may be listed under a different name. Search package.json for any package containing live-updates from @capacitor scope.npx cap sync fails after plugin swap → Verify the installed @capawesome/capacitor-live-update version matches the Capacitor version in package.json.LiveUpdate.ready() is likely not called early enough. Add it as the first call in app initialization.autoUpdateStrategy: "background" → Updates only checked if last check was >15 minutes ago. Force-close and restart the app. Check device logs for Live Update SDK output.LiveUpdates is not defined or similar runtime errors → Ensure all imports were updated from @capacitor/live-updates to @capawesome/capacitor-live-update and the class name changed from LiveUpdates to LiveUpdate.Deploy is not defined → The project uses the legacy Cordova SDK (cordova-plugin-ionic). Read references/cordova-sdk-migration.md for the full method mapping.activeApplicationPathChanged is not a property or sync result checks fail → The Capawesome SDK returns { nextBundleId } instead of { activeApplicationPathChanged }. Update all sync result checks.setConfig is not a function → setConfig() requires @capawesome/capacitor-live-update v7.4.0+ (Capacitor 7/8 only). For Capacitor 6, remove runtime config calls and set configuration statically in capacitor.config.ts.npx @capawesome/cli login. For CI/CD, verify the CAPAWESOME_CLOUD_TOKEN secret is set correctly.npx @capawesome/cli apps:certificates:create. Read the capawesome-cloud skill's references/certificates-android.md or references/certificates-ios.md.invalid source release → Set JAVA_VERSION environment variable in the build environment. Read the capawesome-cloud skill's references/build-troubleshooting.md.capawesome-cloud skill's references/apple-app-store-credentials.md or references/google-play-store-credentials.md.CAPAWESOME_CLOUD_TOKEN is available as a secret in the CI/CD environment.capawesome-cloud — Referenced throughout this skill for Native Builds and App Store Publishing setup.ionic-enterprise-sdk-migration — If the project also uses discontinued Ionic Enterprise SDK plugins (Auth Connect, Identity Vault, Secure Storage), use this skill to migrate them to Capawesome alternatives.tools
Guides the agent through migrating Capacitor apps from discontinued Ionic Enterprise SDK plugins (Auth Connect, Identity Vault, Secure Storage) to their Capawesome alternatives (OAuth, Vault, Biometrics, Secure Preferences, SQLite). Covers dependency detection, side-by-side API mapping, code replacement, and platform-specific configuration for each plugin pair. Do not use for migrating Capacitor apps or plugins to a newer version, setting up Capawesome Cloud, or non-Capacitor mobile frameworks.
tools
Guides the agent through installing, configuring, and using Capacitor plugins from six sources — official Capacitor plugins, Capawesome plugins, Capacitor Community plugins, Capacitor Firebase plugins, Capacitor MLKit plugins, and RevenueCat plugins. Covers installation, platform-specific configuration (Android and iOS), and basic usage examples. Do not use for migrating Capacitor apps or plugins to a newer version, setting up Capacitor Live Updates, or non-Capacitor mobile frameworks.
tools
Guides the agent through Ionic Vue development patterns — project structure, Vue-specific Ionic components (IonPage, IonRouterOutlet, IonTabs), navigation with Vue Router and useIonRouter, Ionic lifecycle hooks (onIonViewWillEnter, onIonViewDidEnter, onIonViewWillLeave, onIonViewDidLeave), composable utilities (useIonRouter, useBackButton, useKeyboard), tab-based routing, lazy loading, platform detection with isPlatform, and troubleshooting common Vue-specific issues. Do not use for general Ionic component theming or CLI usage (use ionic-app-development), creating a new Ionic app (use ionic-app-creation), Capacitor-specific Vue patterns without Ionic (use capacitor-vue), upgrading Ionic versions (use ionic-app-upgrades), or non-Vue frameworks like Angular or React.
development
Guides the agent through Ionic Framework development with React — project structure, React-specific Ionic components, IonReactRouter and navigation patterns, Ionic lifecycle hooks (useIonViewWillEnter, useIonViewDidEnter, useIonViewWillLeave, useIonViewDidLeave), state management integration, and React-specific best practices for Ionic apps. Do not use for plain Capacitor React apps without Ionic (use capacitor-react), Ionic with Angular or Vue, creating a new Ionic app (use ionic-app-creation), upgrading Ionic to a newer version (use ionic-app-upgrades), or general Ionic component usage without React-specific context (use ionic-app-development).