Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Turn web apps into native mobile apps with Capacitor — access native device APIs from JavaScript. Use when someone asks to "convert my website to a mobile app", "Capacitor", "web to native app", "access camera from JavaScript", "deploy web app to App Store", "hybrid mobile app", or "Ionic Capacitor". Covers native API access, plugin system, web-to-native bridge, and app store deployment.
.claude/skills/terminalskills-capacitor/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-15 | ✗→✓ | ▲ Improved | 163% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 56% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 29% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 19% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 51% | 0% |
Capacitor wraps your web app in a native container and gives it access to native device APIs — camera, file system, push notifications, biometrics, geolocation, and more. Your existing React/Vue/Angular/Svelte app becomes an iOS and Android app without rewriting in Swift or Kotlin. Built by the Ionic team, it's the modern replacement for Cordova/PhoneGap.
bashnpm install @capacitor/core @capacitor/cli npx cap init "My App" com.mycompany.myapp # Add platforms npm install @capacitor/ios @capacitor/android npx cap add ios npx cap add android
bash# Build your web app first npm run build # Copy web assets to native projects npx cap sync # Open in native IDE npx cap open ios # Opens Xcode npx cap open android # Opens Android Studio # Or run directly npx cap run ios --target "iPhone 15" npx cap run android
bash# Install plugins npm install @capacitor/camera @capacitor/filesystem @capacitor/push-notifications npm install @capacitor/haptics @capacitor/share @capacitor/browser npx cap sync
typescript// src/native/camera.ts — Access the device camera import { Camera, CameraResultType, CameraSource } from "@capacitor/camera"; async function takePhoto(): Promise<string> { const photo = await Camera.getPhoto({ quality: 80, allowEditing: false, resultType: CameraResultType.Uri, source: CameraSource.Camera, }); return photo.webPath!; // File URI to display in <img> } async function pickFromGallery(): Promise<string[]> { const photos = await Camera.pickImages({ quality: 80, limit: 5, }); return photos.photos.map((p) => p.webPath!); }
typescript// src/native/notifications.ts — Push notifications import { PushNotifications } from "@capacitor/push-notifications"; async function registerPush() { const permission = await PushNotifications.requestPermissions(); if (permission.receive === "granted") { await PushNotifications.register(); } PushNotifications.addListener("registration", (token) => { console.log("FCM Token:", token.value); // Send token to your server }); PushNotifications.addListener("pushNotificationReceived", (notification) => { console.log("Received:", notification.title, notification.body); }); }
typescript// src/native/filesystem.ts — File system access import { Filesystem, Directory } from "@capacitor/filesystem"; async function saveFile(data: string, filename: string) { await Filesystem.writeFile({ path: filename, data: data, directory: Directory.Documents, }); } async function readFile(filename: string): Promise<string> { const result = await Filesystem.readFile({ path: filename, directory: Directory.Documents, }); return result.data as string; }
typescript// src/utils/platform.ts — Adapt behavior per platform import { Capacitor } from "@capacitor/core"; export const isNative = Capacitor.isNativePlatform(); export const platform = Capacitor.getPlatform(); // 'ios' | 'android' | 'web' // Use native features when available, fallback to web async function share(text: string) { if (isNative) { const { Share } = await import("@capacitor/share"); await Share.share({ text }); } else { navigator.share?.({ text }) ?? navigator.clipboard.writeText(text); } }
User prompt: "I have a React web app. Make it available on iOS and Android."
The agent will add Capacitor, configure native projects, add platform detection for native features, and prepare for App Store/Play Store submission.
User prompt: "Add photo capture and file upload to my mobile web app."
The agent will install Capacitor camera and filesystem plugins, create a photo capture component with gallery fallback, and implement file upload.
npx cap sync after every web build — copies assets to native projectsnpx cap run for testing — faster than opening IDE each timeCapacitor.isNativePlatform() for conditional native featuresnpx cap run ios --livereloadcapacitor.config.ts — configure server URL, plugins, app info| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 6,859 | 3,758 | -45% | 1 | 1 | 0% | 1,285 | 2,002 | +56% | 0 | 0 | — |
case-02 | pass→pass | 10,914 | 8,077 | -26% | 1 | 1 | 0% | 2,066 | 2,673 | +29% | 0 | 0 | — |
case-03 | pass→pass | 14,126 | 9,616 | -32% | 1 | 1 | 0% | 2,385 | 2,840 | +19% | 0 | 0 | — |
case-04 | pass→pass | 6,274 | 3,291 | -48% | 1 | 1 | 0% | 1,285 | 1,940 | +51% | 0 | 0 | — |
case-05 | pass→pass | 4,400 | 1,954 | -56% | 1 | 1 | 0% | 645 | 1,628 | +152% | 0 | 0 | — |
case-06 | pass→pass | 7,051 | 4,904 | -30% | 1 | 1 | 0% | 1,396 | 2,199 | +58% | 0 | 0 | — |
case-07 | pass→pass | 3,149 | 2,745 | -13% | 1 | 1 | 0% | 488 | 1,791 | +267% | 0 | 0 | — |
case-08 | pass→pass | 3,083 | 2,471 | -20% | 1 | 1 | 0% | 610 | 1,683 | +176% | 0 | 0 | — |
case-09 | pass→pass | 4,557 | 2,676 | -41% | 1 | 1 | 0% | 810 | 1,761 | +117% | 0 | 0 | — |
case-10 | pass→pass | 6,737 | 5,971 | -11% | 1 | 1 | 0% | 1,244 | 2,434 | +96% | 0 | 0 | — |
case-11 | pass→pass | 4,648 | 2,590 | -44% | 1 | 1 | 0% | 836 | 1,718 | +106% | 0 | 0 | — |
case-12 | pass→pass | 2,233 | 1,641 | -27% | 1 | 1 | 0% | 339 | 1,509 | +345% | 0 | 0 | — |
case-13 | pass→pass | 3,235 | 2,452 | -24% | 1 | 1 | 0% | 590 | 1,689 | +186% | 0 | 0 | — |
case-14 | fail→fail | 14,392 | 12,414 | -14% | 1 | 1 | 0% | 2,748 | 3,961 | +44% | 0 | 0 | — |
case-15 | fail→pass | 3,351 | 2,673 | -20% | 1 | 1 | 0% | 651 | 1,711 | +163% | 0 | 0 | — |
case-16 | pass→pass | 7,131 | 1,206 | -83% | 1 | 1 | 0% | 1,249 | 1,449 | +16% | 0 | 0 | — |
case-17 | pass→pass | 3,257 | 2,739 | -16% | 1 | 1 | 0% | 525 | 1,787 | +240% | 0 | 0 | — |
case-18 | pass→pass | 8,843 | 4,224 | -52% | 1 | 1 | 0% | 1,538 | 2,008 | +31% | 0 | 0 | — |
case-19 | pass→pass | 3,250 | 2,468 | -24% | 1 | 1 | 0% | 648 | 1,668 | +157% | 0 | 0 | — |
case-20 | pass→pass | 7,760 | 5,672 | -27% | 1 | 1 | 0% | 1,776 | 2,450 | +38% | 0 | 0 | — |
case-21 | pass→pass | 11,017 | 7,435 | -33% | 1 | 1 | 0% | 2,442 | 2,835 | +16% | 0 | 0 | — |
case-22 | pass→pass | 13,820 | 8,991 | -35% | 1 | 1 | 0% | 3,172 | 3,286 | +4% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +5 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.