Guides migration from Apache Cordova/PhoneGap to Capacitor including plugin equivalents, config updates, platform addition for iOS/Android, and key differences.
npx claudepluginhub cap-go/capgo-skills --plugin capacitor-app-migrationsThis skill is limited to using the following tools:
Step-by-step guide for migrating from Apache Cordova/PhoneGap to Capacitor.
Migrates web apps, PWAs, SPAs to store-ready Capacitor iOS/Android apps. Addresses thin WebView rejections, native UX, permissions, offline support, billing, testing, Capgo updates.
Upgrades Capacitor apps from v4 to v5 by updating packages, reviewing migration notes, running npm install and cap sync, and verifying iOS/Android builds. For v4 to v5 migrations only.
Upgrades Capacitor plugins from v4 to v5: updates peer dependencies, reviews migration notes, edits native iOS/Android code, updates example apps, runs npm install, syncs and verifies.
Share bugs, ideas, or general feedback.
Step-by-step guide for migrating from Apache Cordova/PhoneGap to Capacitor.
Current migration-related packages:
!node -e "const fs=require('fs');if(!fs.existsSync('package.json'))process.exit(0);const pkg=JSON.parse(fs.readFileSync('package.json','utf8'));const out=[];for(const section of ['dependencies','devDependencies']){for(const [name,version] of Object.entries(pkg[section]||{})){if(name.includes('cordova')||name.startsWith('@capacitor/')||name.startsWith('@ionic-enterprise/'))out.push(section+'.'+name+'='+version)}}console.log(out.sort().join('\n'))"
Relevant config and platform paths:
!find . -maxdepth 3 \( -name 'config.xml' -o -name 'capacitor.config.json' -o -name 'capacitor.config.ts' -o -name 'capacitor.config.js' -o -path './ios' -o -path './android' \)
| Aspect | Cordova | Capacitor |
|---|---|---|
| Native IDE | Builds via CLI | First-class Xcode/Android Studio |
| Plugin Management | Separate ecosystem | npm packages |
| Updates | Full app store review | Live updates with Capgo |
| Web App Platform | Any | Any (React, Vue, Angular, etc.) |
| Maintenance | Slowing down | Active development |
| TypeScript | Limited | Full support |
| Modern APIs | Older patterns | Modern Promise-based APIs |
Start from the injected snapshot above before falling back to manual inspection.
Check Cordova version:
cordova --version
cordova platform version
List installed plugins:
cordova plugin list
Review config.xml:
cat config.xml
In your existing Cordova project:
# Install Capacitor
npm install @capacitor/core @capacitor/cli
# Initialize Capacitor
npx cap init
When prompted:
com.company.app)www for Cordova projectsCapacitor doesn't modify web assets. Add platforms separately:
# Add iOS platform
npm install @capacitor/ios
npx cap add ios
# Add Android platform
npm install @capacitor/android
npx cap add android
This creates:
ios/ directory with Xcode projectandroid/ directory with Android Studio projectCRITICAL: Check plugin compatibility first.
| Cordova Plugin | Capacitor Equivalent | Install Command |
|---|---|---|
| cordova-plugin-camera | @capacitor/camera | npm install @capacitor/camera |
| cordova-plugin-geolocation | @capacitor/geolocation | npm install @capacitor/geolocation |
| cordova-plugin-device | @capacitor/device | npm install @capacitor/device |
| cordova-plugin-network-information | @capacitor/network | npm install @capacitor/network |
| cordova-plugin-statusbar | @capacitor/status-bar | npm install @capacitor/status-bar |
| cordova-plugin-splashscreen | @capacitor/splash-screen | npm install @capacitor/splash-screen |
| cordova-plugin-keyboard | @capacitor/keyboard | npm install @capacitor/keyboard |
| cordova-plugin-dialogs | @capacitor/dialog | npm install @capacitor/dialog |
| cordova-plugin-file | @capacitor/filesystem | npm install @capacitor/filesystem |
| cordova-plugin-inappbrowser | @capacitor/browser | npm install @capacitor/browser |
| cordova-plugin-media | @capacitor/media | Custom or use @capgo plugins |
| cordova-plugin-vibration | @capacitor/haptics | npm install @capacitor/haptics |
| cordova-plugin-local-notifications | @capacitor/local-notifications | npm install @capacitor/local-notifications |
| cordova-plugin-push | @capacitor/push-notifications | npm install @capacitor/push-notifications |
For biometrics:
# Cordova
cordova plugin add cordova-plugin-fingerprint-aio
# Capacitor
npm install @capgo/capacitor-native-biometric
For payments:
# Cordova
cordova plugin add cordova-plugin-purchase
# Capacitor
npm install @capgo/capacitor-purchases
For social login:
# Facebook
npm install @capgo/capacitor-social-login
# Google
npm install @codetrix-studio/capacitor-google-auth
Check the full plugin catalog: https://github.com/Cap-go/awesome-capacitor
Cordova (old):
document.addEventListener('deviceready', () => {
navigator.camera.getPicture(success, error, options);
});
Capacitor (new):
import { Camera } from '@capacitor/camera';
// No deviceready event needed
const image = await Camera.getPhoto({
quality: 90,
allowEditing: true,
resultType: CameraResultType.Uri
});
Device Information:
// Cordova
const uuid = device.uuid;
const platform = device.platform;
// Capacitor
import { Device } from '@capacitor/device';
const info = await Device.getId();
const platform = await Device.getInfo();
Network Status:
// Cordova
const networkState = navigator.connection.type;
// Capacitor
import { Network } from '@capacitor/network';
const status = await Network.getStatus();
console.log('Connected:', status.connected);
Geolocation:
// Cordova
navigator.geolocation.getCurrentPosition(success, error);
// Capacitor
import { Geolocation } from '@capacitor/geolocation';
const position = await Geolocation.getCurrentPosition();
Capacitor doesn't need deviceready. Plugins work immediately.
// Cordova (remove this)
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady() {
// Your code
}
// Capacitor (just use directly)
import { Camera } from '@capacitor/camera';
async function takePicture() {
const photo = await Camera.getPhoto();
}
Cordova uses config.xml. Capacitor uses capacitor.config.ts
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.company.app', // From config.xml widget id
appName: 'My App', // From config.xml name
webDir: 'www', // From Cordova build output
server: {
androidScheme: 'https'
},
plugins: {
SplashScreen: {
launchShowDuration: 3000,
backgroundColor: '#ffffff',
androidScaleType: 'CENTER_CROP',
showSpinner: false
}
}
};
export default config;
Preferences:
<!-- Cordova config.xml -->
<preference name="Orientation" value="portrait" />
<preference name="StatusBarOverlaysWebView" value="false" />
<preference name="StatusBarBackgroundColor" value="#000000" />
Capacitor equivalent:
@capacitor/status-bar pluginPlatform-specific config:
<!-- Cordova config.xml -->
<platform name="ios">
<allow-intent href="itms:*" />
</platform>
Capacitor equivalent:
// capacitor.config.ts
const config: CapacitorConfig = {
ios: {
contentInset: 'always',
},
android: {
allowMixedContent: true,
}
};
Capacitor requires explicit permission configuration.
Add to ios/App/App/Info.plist:
<key>NSCameraUsageDescription</key>
<string>We need camera access to take photos</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need photo library access to select images</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>We need location to show nearby places</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need microphone access for audio recording</string>
Add to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
Sync web code with native projects:
npx cap sync
This copies:
www/ to native projectsBuild for iOS:
npx cap open ios
# Then build in Xcode (Cmd+R)
Build for Android:
npx cap open android
# Then build in Android Studio (Run)
Test all plugin functionality:
Check for:
Once migration is complete and tested:
# Remove Cordova platforms
cordova platform remove ios
cordova platform remove android
# Remove Cordova
npm uninstall cordova
npm uninstall cordova-ios
npm uninstall cordova-android
# Remove Cordova plugins
cordova plugin list | xargs -I {} cordova plugin remove {}
# Remove config.xml (after backing up)
mv config.xml config.xml.backup
Problem:
Error: Plugin not found
Solution:
npm listnpx cap syncProblem: Cordova's deviceready event doesn't exist in Capacitor.
Solution:
Remove all deviceready event listeners. Capacitor plugins work immediately.
// Remove this
document.addEventListener('deviceready', onDeviceReady);
// Use this
import { App } from '@capacitor/app';
App.addListener('appStateChange', (state) => {
console.log('App state changed:', state.isActive);
});
Problem: App shows white screen or crashes.
Solution:
webDir in capacitor.config.ts points to correct build outputnpm run buildnpx cap syncProblem: Camera/location/etc. fail silently.
Solution:
import { Camera } from '@capacitor/camera';
// Capacitor handles permission prompts automatically
const photo = await Camera.getPhoto();
Problem: Some third-party Cordova plugins still reference Cordova global.
Solution: Use the Capacitor Cordova compatibility layer:
npm install cordova-plugin-example
npx cap sync
Capacitor includes Cordova compatibility, but:
You can run Cordova and Capacitor side-by-side during migration.
When ready, remove Cordova entirely.
cordova plugin listnpm install @capacitor/plugin-namedeviceready event listenersnpx cap syncCapacitor enables instant updates without app store review.
After migration, add Capgo for OTA updates:
# Install Capgo plugin
npm install @capgo/capacitor-updater
# Create account at capgo.app
npm install -g @capgo/cli
capgo login
# Initialize and deploy
capgo init
npm run build
capgo upload
Users get updates instantly. See the capgo-live-updates skill for details.
| App Size | Estimated Time |
|---|---|
| Small (1-3 plugins) | 2-4 hours |
| Medium (4-8 plugins) | 1-2 days |
| Large (9+ plugins) | 3-5 days |
| Enterprise (custom plugins) | 1-2 weeks |
After migrating from Cordova to Capacitor:
✅ Faster development - Direct access to Xcode/Android Studio ✅ Live updates - Deploy updates without app store review (with Capgo) ✅ Better TypeScript - Full type safety ✅ Modern APIs - Promise-based, async/await ✅ Active maintenance - Regular updates and improvements ✅ Better debugging - Native IDE debugging tools ✅ Improved performance - Optimized native bridge
capacitor-ci-cd skill)capgo-live-updates skill)capacitor-app-store skill)