Install
openclaw skills install capacitor-expertA comprehensive starting point for AI agents to work with Capacitor. Covers core concepts, CLI, app creation, plugins, framework integration, best practices, storage, security, testing, troubleshooting, upgrading, and Capawesome Cloud (live updates, native builds, app store publishing). Pair with the other Capacitor skills in this collection for deeper topic-specific guidance.
openclaw skills install capacitor-expertComprehensive reference for building cross-platform apps with Capacitor. Covers architecture, CLI, plugins, framework integration, best practices, and Capawesome Cloud.
Capacitor is a cross-platform native runtime for building web apps that run natively on iOS, Android, and the web. The web app runs in a native WebView, and Capacitor provides a bridge to native APIs via plugins.
A Capacitor app has three layers:
Data passed across the bridge must be JSON-serializable. Pass files as paths, not base64.
my-app/
android/ # Native Android project (committed to VCS)
ios/ # Native iOS project (committed to VCS)
App/
App/ # iOS app source files
App.xcodeproj/
src/ # Web app source code
dist/ or www/ or build/ # Built web assets
capacitor.config.ts # Capacitor configuration
package.json
The android/ and ios/ directories are full native projects -- they are committed to version control and can be modified directly.
capacitor.config.ts (preferred) or capacitor.config.json controls app behavior:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'My App',
webDir: 'dist',
server: {
// androidScheme: 'https', // default in Cap 6+
},
};
export default config;
For details, see App Configuration.
# 1. Create a web app (React example with Vite)
npm create vite@latest my-app -- --template react-ts
cd my-app && npm install
# 2. Install Capacitor
npm install @capacitor/core
npm install -D @capacitor/cli
# 3. Initialize Capacitor
npx cap init "My App" com.example.myapp --web-dir dist
# 4. Build web assets
npm run build
# 5. Add platforms
npm install @capacitor/android @capacitor/ios
npx cap add android
npx cap add ios
# 6. Sync and run
npx cap sync
npx cap run android
npx cap run ios
Web asset directories by framework:
dist/<project-name>/browser (Angular 17+ with application builder)distdistwwwFor the full guided creation flow, see capacitor-app-creation.
All commands: npx cap <command>. Most important commands:
| Command | Purpose |
|---|---|
npx cap init <name> <id> | Initialize Capacitor in a project |
npx cap add <platform> | Add Android or iOS platform |
npx cap sync | Copy web assets + update native dependencies (run after every plugin install, config change, or web build) |
npx cap copy | Copy web assets only (faster, no native dependency update) |
npx cap run <platform> | Build, sync, and deploy to device/emulator |
npx cap run <platform> -l --external | Run with live reload |
npx cap open <platform> | Open native project in IDE |
npx cap build <platform> | Build native project |
npx cap doctor | Diagnose configuration issues |
npx cap ls | List installed plugins |
npx cap migrate | Automated upgrade to newer Capacitor version |
For the full CLI reference, see CLI Reference.
Capacitor works with any web framework. Framework-specific patterns:
NgZone.run().ngOnInit, remove in ngOnDestroy.For details, see capacitor-angular.
useCamera, useNetwork) that wrap Capacitor plugins.useEffect for listener registration with cleanup to prevent memory leaks.For details, see capacitor-react.
useCamera, useNetwork) using Vue 3 Composition API.onMounted, remove in onUnmounted.ref changes automatically (no NgZone equivalent needed).For details, see capacitor-vue.
Plugins are Capacitor's extension mechanism. Each plugin exposes a JS API backed by native implementations.
@capacitor/*) -- Camera, Filesystem, Geolocation, Preferences, etc.@capawesome/*, @capawesome-team/*) -- SQLite, NFC, Biometrics, Live Update, etc.@capacitor-community/*) -- AdMob, BLE, SQLite, Stripe, etc.@capacitor-firebase/*) -- Analytics, Auth, Messaging, Firestore, etc.@capacitor-mlkit/*) -- Barcode scanning, face detection, translation.@revenuecat/purchases-capacitor) -- In-app purchases.npm install @capacitor/camera
npx cap sync
After installation, apply any required platform configuration (permissions in AndroidManifest.xml, Info.plist entries, etc.) as documented by the plugin.
import { Camera, CameraResultType } from '@capacitor/camera';
const photo = await Camera.getPhoto({
quality: 90,
resultType: CameraResultType.Uri,
});
For the full plugin index (160+ plugins) and setup guides, see capacitor-plugins.
Create custom Capacitor plugins with native iOS (Swift) and Android (Java/Kotlin) implementations:
npm init @capacitor/plugin@latest.src/definitions.ts.src/web.ts.ios/Sources/.android/src/main/java/.npm run verify.Key rules:
registerPlugin() name in src/index.ts must match jsName on iOS and @CapacitorPlugin(name = "...") on Android.@objc and must be listed in pluginMethods (CAPBridgedPlugin).@PluginMethod() annotation and must be public.For full details, see capacitor-plugin-development.
import { Capacitor } from '@capacitor/core';
const platform = Capacitor.getPlatform(); // 'android' | 'ios' | 'web'
if (Capacitor.isNativePlatform()) { /* native-only code */ }
if (Capacitor.isPluginAvailable('Camera')) { /* plugin available */ }
Follow the check-then-request pattern:
const status = await Camera.checkPermissions();
if (status.camera !== 'granted') {
const requested = await Camera.requestPermissions();
if (requested.camera === 'denied') {
// Guide user to app settings -- cannot re-request on iOS
return;
}
}
const photo = await Camera.getPhoto({ ... });
Always wrap plugin calls in try-catch:
try {
const photo = await Camera.getPhoto({ resultType: CameraResultType.Uri });
} catch (error) {
if (error.message === 'User cancelled photos app') {
// Not an error
} else {
console.error('Camera error:', error);
}
}
For full details, see Cross-Platform Best Practices.
Deep links open specific content in the app from external URLs.
apple-app-site-association hosted at https://<domain>/.well-known/.assetlinks.json hosted at https://<domain>/.well-known/.import { App } from '@capacitor/app';
App.addListener('appUrlOpen', (event) => {
const path = new URL(event.url).pathname;
// Route to the appropriate page
});
applinks:<domain> to Associated Domains capability in ios/App/App/App.entitlements.<intent-filter android:autoVerify="true"> to android/app/src/main/AndroidManifest.xml.For full setup, see Deep Links.
| Requirement | Solution |
|---|---|
| App settings, preferences | @capacitor/preferences (native key-value, persists reliably) |
| Sensitive data (tokens, credentials) | @capawesome-team/capacitor-secure-preferences (Keychain/Keystore) |
| Relational data, offline-first | SQLite (@capawesome-team/capacitor-sqlite or @capacitor-community/sqlite) |
| Files, images, documents | @capacitor/filesystem |
Do NOT use localStorage, IndexedDB, or cookies for persistent data -- the OS can evict them (especially on iOS).
For details, see Storage.
@capawesome-team/capacitor-secure-preferences) for tokens and credentials, not localStorage or @capacitor/preferences.<meta> CSP tag in index.html.webContentsDebuggingEnabled: false in capacitor.config.ts.PrivacyInfo.xcprivacy) -- required for iOS 17+ when using privacy-sensitive APIs.For details, see Security.
Mock Capacitor plugins in Jest/Vitest since tests run in Node.js, not a WebView:
vi.mock('@capacitor/camera', () => ({
Camera: {
getPhoto: vi.fn().mockResolvedValue({
webPath: 'https://example.com/photo.jpg',
}),
},
}));
webContentsDebuggingEnabled: true, open chrome://inspect in Chrome.webContentsDebuggingEnabled: true, use Safari > Develop menu > select device.For details, see Testing.
npx cap sync fails: Verify @capacitor/core and @capacitor/cli versions match. Run cd android && ./gradlew clean.cd android && ./gradlew clean, then rebuild.npx cap sync after plugin installation. Verify Gradle sync completed.ANDROID_HOME is set. Install missing SDK versions via Android Studio SDK Manager.npx cap sync ios. For CocoaPods: cd ios/App && pod install --repo-update.ios/App/Pods and re-run pod install.webDir in capacitor.config.ts matches the actual build output directory.--external flag.npx cap sync. Verify plugin is in package.json dependencies.Capacitor is not defined: Install @capacitor/core (npm install @capacitor/core).For full troubleshooting, see Android Troubleshooting and iOS Troubleshooting.
Capacitor supports upgrades across major versions (4 through 8). Apply each major version jump sequentially -- do not skip intermediate versions.
| Current to Target | Node.js | Xcode | Android Studio |
|---|---|---|---|
| to 5 | 16+ | 14.1+ | Flamingo 2022.2.1+ |
| to 6 | 18+ | 15.0+ | Hedgehog 2023.1.1+ |
| to 7 | 20+ | 16.0+ | Ladybug 2024.2.1+ |
| to 8 | 22+ | 26.0+ | Otter 2025.2.1+ |
Quick automated upgrade:
npx cap migrate
npx cap sync
If npx cap migrate fails partially, apply manual steps from the upgrade guides.
For app upgrades, see capacitor-app-upgrades. For plugin upgrades, see capacitor-plugin-upgrades.
Capawesome Cloud provides cloud infrastructure for Capacitor apps: native builds, live updates, and automated app store publishing.
Website: capawesome.io | Cloud Services: cloud.capawesome.io
# Install and authenticate
npx @capawesome/cli login
# Create an app
npx @capawesome/cli apps:create
Deploy over-the-air (OTA) web updates to Capacitor apps without going through the app stores. Users receive updates immediately on next app launch.
Setup:
# Install the live update plugin
npm install @capawesome/capacitor-live-update
npx cap sync
Configure in capacitor.config.ts:
const config: CapacitorConfig = {
plugins: {
LiveUpdate: {
appId: '<APP_ID>',
autoUpdate: true,
},
},
};
Deploy an update:
npm run build
npx @capawesome/cli apps:liveupdates:upload --app-id <APP_ID>
Build iOS and Android apps in the cloud without local build environments. Supports signing certificates, environments, and build configuration.
# Trigger a build
npx @capawesome/cli apps:builds:create --app-id <APP_ID> --platform android
# Download the artifact
npx @capawesome/cli apps:builds:download --app-id <APP_ID> --build-id <BUILD_ID>
Automate submissions to Apple App Store (TestFlight) and Google Play Store.
# Create a deployment destination
npx @capawesome/cli apps:destinations:create --app-id <APP_ID>
# Deploy a build
npx @capawesome/cli apps:deployments:create --app-id <APP_ID> --build-id <BUILD_ID>
Use token-based auth for CI/CD pipelines:
npx @capawesome/cli login --token <TOKEN>
npx @capawesome/cli apps:builds:create --app-id <APP_ID> --platform ios --detached
For full Capawesome Cloud setup, see capawesome-cloud. For the Capawesome CLI reference, see capawesome-cli.
Set up push notifications using Firebase Cloud Messaging (FCM) via @capacitor-firebase/messaging:
npm install @capacitor-firebase/messaging firebase
npx cap sync
Requires Firebase project setup, platform-specific configuration (APNs for iOS, google-services.json for Android), and permission handling.
For the full setup guide, see capacitor-push-notifications.
Set up in-app purchases and subscriptions with either:
@capawesome-team/capacitor-purchases) -- lightweight, no third-party backend, requires Capawesome Insiders license.@revenuecat/purchases-capacitor) -- full managed backend with receipt validation, analytics, and integrations.Both require App Store Connect (iOS) and/or Google Play Console (Android) product configuration.
For the full setup guide, see capacitor-in-app-purchases.