Mobile & Capacitor

Capacitor Mobile Apps mit Claude Code: iOS & Android 2026

Von der Web-App zur nativen App — Capacitor 6, Native Plugins, Push-Notifications und App-Store-Deployment mit KI-Unterstützung.

📅 6. Mai 2026 ⏱ 11 min Lesezeit 👤 SpockyMagicAI Team

Inhaltsverzeichnis

  1. Capacitor 6 Setup & Projektkonfiguration
  2. Native Plugins: Kamera, GPS, Dateisystem
  3. Push Notifications: FCM & APNs
  4. Custom Native Plugins: Swift & Kotlin
  5. Live Reload & Debugging Workflow
  6. App Store Deployment & CI/CD

Cross-platform Mobile-Entwicklung war lange ein Kompromiss: entweder native Performance oder Web-Entwickler-Produktivität. Capacitor 6 ändert das grundlegend — und Claude Code macht den gesamten Workflow von der Konfiguration bis zum App-Store-Release effizienter als je zuvor.

In diesem Guide zeigen wir, wie du 2026 mit Capacitor und Claude Code produktiv native iOS- und Android-Apps entwickelst. Konkrete Code-Beispiele, echte Fehler-Szenarien und bewährte Deployment-Strategien inklusive.

Was ist Capacitor?

Capacitor ist ein Open-Source Native Runtime von Ionic, der Web-Apps (React, Vue, Angular, Vanilla JS) in native iOS- und Android-Apps verwandelt. Im Gegensatz zu React Native oder Flutter bleibt deine gesamte App-Logik in Web-Technologien — Capacitor stellt lediglich eine Bridge zu nativen APIs bereit.

1. Capacitor 6 Setup & Projektkonfiguration

Der einfachste Einstieg ist mit Claude Code: Beschreibe deine App und lass dir das komplette Setup generieren. Claude kennt die aktuellen Capacitor-APIs und vermeidet veraltete Patterns aus älteren Versionen.

Installation & Initialisierung

# Voraussetzungen prüfen node --version # >= 18.0.0 npm --version # >= 9.0.0 # Neue Web-App (hier mit Vite + React) npm create vite@latest my-cap-app -- --template react-ts cd my-cap-app npm install # Capacitor Core + CLI installieren npm install @capacitor/core npm install -D @capacitor/cli # Capacitor initialisieren npx cap init "MeineApp" "com.meineapp.app" --web-dir dist # Plattformen hinzufügen npx cap add ios npx cap add android
Claude Code Prompt-Tipp

Sage Claude: "Erstelle mir ein Capacitor 6 Projekt mit Vite React TypeScript, konfiguriere capacitor.config.ts für Deep Links und setze die minimale iOS-Version auf 15." Claude generiert das vollständige Setup inklusive aller Edge Cases.

capacitor.config.ts — die zentrale Konfiguration

import { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { appId: 'com.meineapp.app', appName: 'MeineApp', webDir: 'dist', server: { // Für Live-Reload (nur Development!) url: 'http://192.168.1.100:5173', cleartext: true, }, plugins: { SplashScreen: { launchShowDuration: 2000, backgroundColor: '#0f172a', showSpinner: false, }, PushNotifications: { presentationOptions: ['badge', 'sound', 'alert'], }, LocalNotifications: { smallIcon: 'ic_stat_icon_config_sample', iconColor: '#119eff', }, }, ios: { contentInset: 'automatic', allowsLinkPreview: false, preferredContentMode: 'mobile', }, android: { buildOptions: { keystorePath: 'android/app/release.keystore', keystoreAlias: 'release', }, }, }; export default config;

Build & Sync Workflow

# Web-App bauen npm run build # Native Projekte synchronisieren (nach jedem Build!) npx cap sync # Alternativ: nur kopieren ohne Plugin-Updates npx cap copy # Xcode öffnen (macOS erforderlich für iOS) npx cap open ios # Android Studio öffnen npx cap open android

Package.json Scripts für effizienten Workflow

{ "scripts": { "dev": "vite", "build": "tsc && vite build", "cap:sync": "npm run build && npx cap sync", "cap:ios": "npm run cap:sync && npx cap open ios", "cap:android": "npm run cap:sync && npx cap open android", "cap:run:ios": "npm run build && npx cap run ios", "cap:run:android": "npm run build && npx cap run android" } }

2. Native Plugins: Kamera, GPS & Dateisystem

Die Stärke von Capacitor liegt in seinen offiziellen und Community-Plugins. Jedes Plugin bietet eine einheitliche TypeScript-API, die auf beiden Plattformen funktioniert — die plattformspezifischen Implementierungen übernimmt Capacitor automatisch.

Offizielle Capacitor-Plugins im Überblick

📷 Camera Plugin

Kamera & Galerie-Zugriff, HEIC/JPEG Unterstützung, Qualitätskontrolle

📍 Geolocation Plugin

GPS-Position, Watch-Position, Accuracy-Level, Background Location

📁 Filesystem Plugin

Lesen/Schreiben von Dateien, Verzeichnisverwaltung, App-Sandbox

📳 Haptics Plugin

Vibrations-Feedback, Impact, Notification, Selection Feedback

🔔 StatusBar Plugin

Statusleiste anpassen, Hintergrundfarbe, Stil (light/dark)

🌐 Network Plugin

Verbindungsstatus prüfen, Netzwerk-Typ, Listener für Änderungen

Kamera-Plugin: Installation & Verwendung

# Installation npm install @capacitor/camera npx cap sync
// camera.service.ts import { Camera, CameraResultType, CameraSource } from '@capacitor/camera'; export async function takePhoto(): Promise<string> { const image = await Camera.getPhoto({ quality: 85, allowEditing: false, resultType: CameraResultType.DataUrl, source: CameraSource.Camera, width: 1920, correctOrientation: true, }); if (!image.dataUrl) throw new Error('Kein Bild erhalten'); return image.dataUrl; } export async function pickFromGallery(): Promise<string[]> { const { photos } = await Camera.pickImages({ quality: 80, limit: 10, }); return photos .filter(p => p.webPath) .map(p => p.webPath!); }

Geolocation: GPS-Position abfragen

import { Geolocation, Position } from '@capacitor/geolocation'; export async function getCurrentLocation(): Promise<Position> { // Berechtigungen prüfen const permission = await Geolocation.checkPermissions(); if (permission.location === 'denied') { const requested = await Geolocation.requestPermissions(); if (requested.location === 'denied') { throw new Error('GPS-Berechtigung verweigert'); } } return Geolocation.getCurrentPosition({ enableHighAccuracy: true, timeout: 10000, maximumAge: 0, }); } // Kontinuierliches GPS-Tracking export function watchPosition(callback: (pos: Position) => void) { return Geolocation.watchPosition( { enableHighAccuracy: true }, (position, err) => { if (err) { console.error(err); return; } if (position) callback(position); } ); }

Filesystem: Dateien lesen & schreiben

import { Filesystem, Directory, Encoding } from '@capacitor/filesystem'; export async function saveData(filename: string, data: object) { await Filesystem.writeFile({ path: filename, data: JSON.stringify(data, null, 2), directory: Directory.Documents, encoding: Encoding.UTF8, }); } export async function loadData<T>(filename: string): Promise<T> { const result = await Filesystem.readFile({ path: filename, directory: Directory.Documents, encoding: Encoding.UTF8, }); return JSON.parse(result.data as string) as T; } export async function deleteFile(filename: string) { await Filesystem.deleteFile({ path: filename, directory: Directory.Documents, }); }

Haptics & StatusBar: Polished UX

import { Haptics, ImpactStyle, NotificationType } from '@capacitor/haptics'; import { StatusBar, Style } from '@capacitor/status-bar'; // Feedback bei Button-Tap await Haptics.impact({ style: ImpactStyle.Medium }); // Erfolgsmeldung mit Vibration await Haptics.notification({ type: NotificationType.Success }); // StatusBar für Dark Theme anpassen await StatusBar.setStyle({ style: Style.Dark }); await StatusBar.setBackgroundColor({ color: '#0f172a' });
Wichtig: iOS Info.plist Berechtigungen

Kamera, Galerie und GPS benötigen Privacy-Einträge in der iOS Info.plist. Claude Code kann dir diese automatisch einfügen: "Füge die nötigen NSCamera, NSPhotoLibrary und NSLocation Privacy Keys zur Info.plist hinzu."

3. Push Notifications: FCM & APNs Setup

Push Notifications sind technisch anspruchsvoller, da sie sowohl serverseitige als auch native Konfiguration erfordern. Capacitor abstrahiert die Unterschiede zwischen Firebase Cloud Messaging (Android) und Apple Push Notification Service (iOS).

Installation & Basis-Setup

# Plugin installieren npm install @capacitor/push-notifications npx cap sync # Für Firebase: google-services.json (Android) und GoogleService-Info.plist (iOS) benötigt
// push-notifications.service.ts import { PushNotifications, Token, PushNotificationSchema, ActionPerformed } from '@capacitor/push-notifications'; export async function initPushNotifications() { // Berechtigungen anfordern const permResult = await PushNotifications.requestPermissions(); if (permResult.receive !== 'granted') { console.warn('Push-Benachrichtigungen abgelehnt'); return; } // Bei Firebase/APNs registrieren await PushNotifications.register(); // Device Token empfangen PushNotifications.addListener('registration', (token: Token) => { console.log('Push Token:', token.value); // Token an Backend senden! sendTokenToBackend(token.value); }); // Registrierungsfehler PushNotifications.addListener('registrationError', (error) => { console.error('Registrierungsfehler:', error); }); // Notification empfangen (App im Vordergrund) PushNotifications.addListener('pushNotificationReceived', (notification: PushNotificationSchema) => { console.log('Notification erhalten:', notification); showInAppNotification(notification); } ); // Notification angeklickt PushNotifications.addListener('pushNotificationActionPerformed', (action: ActionPerformed) => { console.log('Notification geklickt:', action); handleNotificationAction(action.notification.data); } ); } async function sendTokenToBackend(token: string) { await fetch('/api/push-token', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ token, platform: typeof (window as any).webkit !== 'undefined' ? 'ios' : 'android' }), }); } function showInAppNotification(notification: PushNotificationSchema) { // Deine UI-Komponente für In-App-Notifications } function handleNotificationAction(data: any) { // Deep Link / Navigation basierend auf notification.data if (data.screen) router.push(data.screen); }

Android: Firebase Cloud Messaging Setup

  1. Firebase Console: Neues Android-Projekt anlegen, google-services.json herunterladen und nach android/app/ kopieren
  2. In android/build.gradle: classpath 'com.google.gms:google-services:4.4.1' hinzufügen
  3. In android/app/build.gradle: apply plugin: 'com.google.gms.google-services' ans Ende anfügen
  4. Firebase SDK Dependencies prüfen: npx cap sync android reicht normalerweise

iOS: APNs Zertifikat & Capabilities

# In Xcode (Signing & Capabilities Tab): # 1. "+ Capability" → "Push Notifications" hinzufügen # 2. "+ Capability" → "Background Modes" → "Remote notifications" aktivieren # 3. Apple Developer: APNs Key (Auth Key) erstellen → .p8 Datei herunterladen # 4. Firebase: iOS-App hinzufügen, APNs Auth Key hochladen # 5. GoogleService-Info.plist → ios/App/App/ kopieren
Claude Code beschleunigt das Setup

Claude kann die exakten Gradle-Änderungen generieren, Xcode-Capability-Schritte erklären und häufige Fehler wie "No valid APN certificate" diagnostizieren. Beschreibe das Problem, Claude liefert die Lösung.

4. Custom Native Plugins: Swift & Kotlin

Wenn offizielle Plugins nicht ausreichen, schreibst du eigene Native Plugins. Claude Code ist hier besonders wertvoll, da es sowohl Swift (iOS) als auch Kotlin (Android) kennt und die Capacitor Bridge-API beherrscht.

Plugin-Struktur erstellen

# Mit Capacitor Plugin-Generator npm init @capacitor/plugin@latest # Folge dem Wizard: Plugin-Name, Package-ID, Verzeichnis # Oder manuell im bestehenden Projekt: mkdir -p android/src/main/java/com/example/myplugin mkdir -p ios/Plugin

TypeScript Interface definieren

// src/definitions.ts export interface BiometricPlugin { /** Prüft ob Biometrie verfügbar ist */ isAvailable(): Promise<{ available: boolean; biometryType: string }>; /** Authentifiziert den Benutzer via Biometrie */ authenticate(options: { reason: string; fallbackTitle?: string; cancelTitle?: string; }): Promise<{ authenticated: boolean }>; } // src/index.ts import { registerPlugin } from '@capacitor/core'; import type { BiometricPlugin } from './definitions'; const Biometric = registerPlugin<BiometricPlugin>('Biometric', { web: () => import('./web').then(m => new m.BiometricWeb()), }); export * from './definitions'; export { Biometric };

Swift Plugin (iOS)

// ios/Plugin/BiometricPlugin.swift import Foundation import Capacitor import LocalAuthentication @objc(BiometricPlugin) public class BiometricPlugin: CAPPlugin, CAPBridgedPlugin { public let identifier = "BiometricPlugin" public let jsName = "Biometric" public let pluginMethods: [CAPPluginMethod] = [ CAPPluginMethod(name: "isAvailable", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "authenticate", returnType: CAPPluginReturnPromise), ] @objc func isAvailable(_ call: CAPPluginCall) { let context = LAContext() var error: NSError? let available = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) var biometryType = "none" if available { switch context.biometryType { case .faceID: biometryType = "faceID" case .touchID: biometryType = "touchID" default: biometryType = "none" } } call.resolve(["available": available, "biometryType": biometryType]) } @objc func authenticate(_ call: CAPPluginCall) { let reason = call.getString("reason") ?? "Authentifizierung erforderlich" let context = LAContext() context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, error in if success { call.resolve(["authenticated": true]) } else { call.resolve(["authenticated": false]) } } } }

Kotlin Plugin (Android)

// android/.../BiometricPlugin.kt package com.example.myplugin import androidx.biometric.BiometricManager import androidx.biometric.BiometricPrompt import androidx.fragment.app.FragmentActivity import com.getcapacitor.Plugin import com.getcapacitor.PluginCall import com.getcapacitor.PluginMethod import com.getcapacitor.annotation.CapacitorPlugin import com.getcapacitor.JSObject import java.util.concurrent.Executor import java.util.concurrent.Executors @CapacitorPlugin(name = "Biometric") class BiometricPlugin : Plugin() { @PluginMethod fun isAvailable(call: PluginCall) { val biometricManager = BiometricManager.from(context) val available = biometricManager.canAuthenticate( BiometricManager.Authenticators.BIOMETRIC_STRONG ) == BiometricManager.BIOMETRIC_SUCCESS val ret = JSObject() ret.put("available", available) ret.put("biometryType", if (available) "fingerprint" else "none") call.resolve(ret) } @PluginMethod fun authenticate(call: PluginCall) { val reason = call.getString("reason") ?: "Authentifizierung erforderlich" val executor: Executor = Executors.newSingleThreadExecutor() val activity = activity as FragmentActivity val callback = object : BiometricPrompt.AuthenticationCallback() { override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { val ret = JSObject() ret.put("authenticated", true) call.resolve(ret) } override fun onAuthenticationFailed() { val ret = JSObject() ret.put("authenticated", false) call.resolve(ret) } } val promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle("Biometrische Authentifizierung") .setSubtitle(reason) .setNegativeButtonText("Abbrechen") .build() activity.runOnUiThread { BiometricPrompt(activity, executor, callback).authenticate(promptInfo) } } }
Claude Code + Custom Plugins

Claude kennt die vollständige Capacitor Bridge API. Beschreibe die native Funktionalität, die du brauchst, und Claude generiert das komplette Plugin: TypeScript-Interface, Swift-Implementierung, Kotlin-Implementierung und die Registrierung im AppDelegate/MainActivity.

5. Live Reload & Debugging Workflow

Ein schneller Feedback-Loop ist entscheidend für produktive Mobile-Entwicklung. Capacitor bietet mit Live Reload und den nativen Debugging-Tools einen professionellen Workflow.

Live Reload Setup

# Lokale IP-Adresse herausfinden ifconfig | grep "inet " | grep -v 127.0.0.1 # capacitor.config.ts: server.url setzen (Development only!) # url: 'http://192.168.1.100:5173' # Terminal 1: Vite Dev Server starten npm run dev -- --host # Terminal 2: Direkt auf Gerät/Simulator deployen mit Live Reload npx cap run ios --livereload --external npx cap run android --livereload --external # Oder mit expliziter IP npx cap run ios --livereload-url=http://192.168.1.100:5173
Sicherheitshinweis: server.url entfernen vor Release!

Die Live-Reload-Konfiguration in capacitor.config.ts MUSS vor dem Production Build entfernt werden. Nutze Environment Variables oder separate Config-Dateien: capacitor.config.prod.ts ohne server.url.

Chrome DevTools für Android

# USB-Debugging auf Android-Gerät aktivieren # (Einstellungen → Entwickleroptionen → USB-Debugging) # In Chrome öffnen: chrome://inspect # Gerät erscheint → "inspect" klicken → vollständige DevTools # Console, Network, Elements, Breakpoints — alles wie im Browser

Xcode Console für iOS

# iOS Simulator in Xcode starten npx cap open ios # Scheme wählen → Simulator → Play # Safari Web Inspector für WKWebView: # Safari → Entwickler → [Simulator-Name] → [App-Name] # Nützliche Xcode Konsolen-Filter: # "WV" → WebView Logs # "CAP" → Capacitor Plugin Calls # "JSContext" → JavaScript Runtime Fehler

Capacitor Plugin Call Debugging

// Alle Plugin-Calls loggen (Development) import { Capacitor } from '@capacitor/core'; if (Capacitor.isNativePlatform()) { console.log('Läuft nativ auf:', Capacitor.getPlatform()); // 'ios' oder 'android' } else { console.log('Läuft im Browser/Web'); } // Plugin-Verfügbarkeit prüfen const isPluginAvailable = Capacitor.isPluginAvailable('Camera'); console.log('Camera Plugin verfügbar:', isPluginAvailable);

Häufige Fehler & Lösungen

Fehler Ursache Lösung
Plugin not implemented npx cap sync vergessen Build neu, dann npx cap sync
NSCameraUsageDescription missing Privacy Key fehlt in Info.plist Key in Xcode eintragen
Weißer Screen auf Android webDir falsch oder Build fehlt npm run build prüfen
Live Reload funktioniert nicht IP nicht erreichbar (Firewall/WLAN) Gerät & PC im selben WLAN

6. App Store Deployment & CI/CD

Das Deployment in den Apple App Store und Google Play ist für viele Teams der komplexeste Teil. Mit dem richtigen Setup und Claude Code als Assistenten ist es ein reproduzierbarer Prozess.

iOS: Xcode Archive & TestFlight

  1. Signing-Zertifikat und Provisioning Profile im Apple Developer Portal erstellen
  2. In Xcode: Signing & Capabilities → Team auswählen → "Automatically manage signing" aktivieren
  3. Product → Archive → Xcode Organizer öffnet sich
  4. "Distribute App" → App Store Connect → Upload
  5. App Store Connect: TestFlight-Tester einladen oder direkt einreichen
# Xcode CLI (für CI/CD) xcodebuild \ -workspace ios/App/App.xcworkspace \ -scheme App \ -configuration Release \ -archivePath build/App.xcarchive \ archive xcodebuild \ -exportArchive \ -archivePath build/App.xcarchive \ -exportPath build/ipa \ -exportOptionsPlist ExportOptions.plist # ExportOptions.plist (Beispiel) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC ...> <plist version="1.0"><dict> <key>method</key><string>app-store</string> <key>teamID</key><string>DEIN_TEAM_ID</string> </dict></plist>

Android: Google Play Console

# Keystore erstellen (einmalig!) keytool -genkey -v \ -keystore android/app/release.keystore \ -alias release \ -keyalg RSA \ -keysize 2048 \ -validity 10000 # android/app/build.gradle: Signing Config android { signingConfigs { release { storeFile file('release.keystore') storePassword System.getenv('KEYSTORE_PASSWORD') keyAlias 'release' keyPassword System.getenv('KEY_PASSWORD') } } buildTypes { release { signingConfig signingConfigs.release minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } # AAB (Android App Bundle) bauen — empfohlen für Play Store cd android && ./gradlew bundleRelease

Fastlane: Automatisiertes Deployment

# Gemfile gem 'fastlane' # fastlane/Fastfile default_platform(:ios) platform :ios do desc "Deploy to TestFlight" lane :beta do increment_build_number(xcodeproj: "ios/App/App.xcodeproj") build_app( workspace: "ios/App/App.xcworkspace", scheme: "App", export_method: "app-store" ) upload_to_testflight(skip_waiting_for_build_processing: true) end desc "Deploy to App Store" lane :release do capture_screenshots build_app(workspace: "ios/App/App.xcworkspace", scheme: "App") upload_to_app_store(force: true) end end platform :android do desc "Deploy to Play Store Internal Track" lane :beta do gradle( task: "bundle", build_type: "Release", project_dir: "android/" ) upload_to_play_store( track: "internal", aab: "android/app/build/outputs/bundle/release/app-release.aab" ) end end

GitHub Actions CI/CD Pipeline

# .github/workflows/mobile-deploy.yml name: Mobile Deploy on: push: branches: [main] tags: ['v*'] jobs: build-android: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci - name: Build web app run: npm run build - name: Sync Capacitor run: npx cap sync android - name: Setup JDK uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' - name: Build Android AAB env: KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} run: | cd android echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > app/release.keystore ./gradlew bundleRelease - name: Upload to Play Store uses: r0adkll/upload-google-play@v1 with: serviceAccountJsonPlainText: ${{ secrets.PLAY_STORE_JSON }} packageName: com.meineapp.app releaseFiles: android/app/build/outputs/bundle/release/*.aab track: internal build-ios: runs-on: macos-14 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - name: Install & Build run: npm ci && npm run build - name: Sync Capacitor run: npx cap sync ios - name: Install Fastlane run: bundle install - name: Deploy to TestFlight env: APP_STORE_CONNECT_API_KEY: ${{ secrets.ASC_API_KEY }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} run: bundle exec fastlane ios beta
Capacitor + Claude Code = schnellerer Release-Zyklus

Claude Code kann den kompletten Fastfile generieren, Gradle-Fehler diagnostizieren und GitHub Actions Workflows für dein spezifisches Setup anpassen. Beschreibe deine Deployment-Anforderungen, Claude liefert produktionsreife CI/CD-Konfigurationen.

Checkliste vor App Store Submission

Fazit: Capacitor 6 + Claude Code 2026

Capacitor hat sich als die pragmatischste Lösung für Teams mit Web-Expertise etabliert. Keine neuen Programmiersprachen lernen, keine separate Codebasis pflegen — und trotzdem voller Zugang zu nativen APIs.

Claude Code beschleunigt jeden Schritt: Plugin-Konfiguration, Native-Code-Generierung in Swift und Kotlin, Debugging-Diagnosen und CI/CD-Setup. Die Kombination aus Capacitors starker Abstraktion und Claudes breitem technischen Wissen reduziert die Time-to-App-Store erheblich.

Key Takeaways:

Mit Claude Code Mobile-Apps entwickeln

Starte deinen kostenlosen Trial und erlebe, wie Claude Code deinen Capacitor-Workflow transformiert — von der Konfiguration bis zum App Store.

Kostenlos ausprobieren →