Mobile & Cross-Platform
Capacitor mit Claude Code: iOS & Android Apps mit TypeScript 2026
Capacitor.js hat sich als die führende Lösung für Cross-Platform Mobile-Entwicklung mit Web-Technologien etabliert. In Kombination mit Claude Code und TypeScript entstehen native iOS- und Android-Apps in einem Bruchteil der Zeit — mit vollem Zugriff auf Native APIs, Push Notifications, Biometrie und App Store Distribution.
📅 6. Mai 2026
⏱ 12 min Lesezeit
✍️ Agentic Movers Team
Was du in diesem Artikel lernst:
- Capacitor-Projekt mit Claude Code aufsetzen und für iOS & Android konfigurieren
- Native APIs: Camera, Filesystem, Geolocation mit TypeScript
- Push Notifications über Firebase & APNS integrieren
- Biometrie-Authentifizierung und sicheren Speicher implementieren
- Over-the-Air (OTA) Live Updates ohne App-Store-Review deployen
- iOS App Store & Google Play Store Deployment vollständig
Der entscheidende Vorteil von Capacitor gegenüber React Native oder Flutter: Du nutzt deine bestehenden Web-Kenntnisse (React, Vue, Angular oder Vanilla TypeScript) und erhältst trotzdem vollständigen Zugriff auf native Gerätefunktionen. Claude Code beschleunigt dabei jeden Entwicklungsschritt — von der Plugin-Konfiguration bis zum Debugging komplexer nativer Bridge-Probleme.
1. Capacitor Setup & Native Build
Setup
Ein neues Capacitor-Projekt beginnt mit der Installation der Core-Abhängigkeiten. Claude Code übernimmt die Konfiguration der nativen Plattformen und erkennt typische Setup-Fehler automatisch.
# Neues Projekt initialisieren
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 "My App" "com.example.myapp" --web-dir dist
# iOS & Android Plattformen hinzufügen
npm install @capacitor/ios @capacitor/android
npx cap add ios
npx cap add android
Nach dem initialen Build synchronisierst du den Web-Code mit den nativen Projekten:
# Web-App bauen & in native Projekte synchronisieren
npm run build
npx cap sync
# In Xcode / Android Studio öffnen
npx cap open ios
npx cap open android
# Live Reload für Entwicklung
npx cap run ios --livereload --external
npx cap run android --livereload --external
capacitor.config.ts — Zentrale Konfiguration:
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'My App',
webDir: 'dist',
server: {
androidScheme: 'https',
iosScheme: 'https',
},
plugins: {
SplashScreen: {
launchShowDuration: 2000,
backgroundColor: '#ffffff',
showSpinner: false,
},
StatusBar: {
style: 'dark',
backgroundColor: '#ffffff',
},
},
};
export default config;
💡 Claude Code Tipp: Wenn du Claude Code das Setup-Problem beschreibst (z. B. "Android SDK nicht gefunden" oder "Xcode Command Line Tools fehlen"), analysiert es die Fehlermeldung und liefert plattformspezifische Fix-Befehle — oft schneller als die offizielle Dokumentation.
Claude Code hilft beim Erkennen von Konfigurationsfehlern in capacitor.config.ts, beim Schreiben plattformspezifischer Permissions in Info.plist (iOS) und AndroidManifest.xml (Android) sowie beim Troubleshooting von Gradle- und CocoaPods-Problemen.
2. Native APIs: Camera & Filesystem
Native
Die Camera-API von Capacitor gibt dir vollständigen Zugriff auf Kamera und Galerie — auf iOS und Android mit identischer TypeScript-Schnittstelle.
# Camera & Filesystem Plugins installieren
npm install @capacitor/camera @capacitor/filesystem @capacitor/preferences
npx cap sync
camera.service.ts — Vollständige Camera-Integration:
import { Camera, CameraResultType, CameraSource, Photo } from '@capacitor/camera';
import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
export class CameraService {
async takePhoto(): Promise<Photo> {
const photo = await Camera.getPhoto({
quality: 90,
allowEditing: false,
resultType: CameraResultType.Uri,
source: CameraSource.Camera,
correctOrientation: true,
});
return photo;
}
async pickFromGallery(): Promise<Photo> {
const photo = await Camera.getPhoto({
quality: 85,
allowEditing: true,
resultType: CameraResultType.Base64,
source: CameraSource.Photos,
});
return photo;
}
async savePhotoToFilesystem(photo: Photo, fileName: string): Promise<string> {
if (!photo.base64String) {
throw new Error('Kein Base64-Daten im Photo-Objekt');
}
const result = await Filesystem.writeFile({
path: `photos/${fileName}.jpeg`,
data: photo.base64String,
directory: Directory.Documents,
recursive: true,
});
return result.uri;
}
async loadPhoto(filePath: string): Promise<string> {
const contents = await Filesystem.readFile({
path: filePath,
directory: Directory.Documents,
});
return `data:image/jpeg;base64,${contents.data}`;
}
async listPhotos(): Promise<string[]> {
try {
const result = await Filesystem.readdir({
path: 'photos',
directory: Directory.Documents,
});
return result.files.map(f => f.name);
} catch {
return [];
}
}
async deletePhoto(fileName: string): Promise<void> {
await Filesystem.deleteFile({
path: `photos/${fileName}`,
directory: Directory.Documents,
});
}
}
Für iOS musst du in Info.plist die Kamera-Permissions deklarieren:
<!-- ios/App/App/Info.plist -->
<key>NSCameraUsageDescription</key>
<string>Diese App benötigt Kamerazugriff für Profilfotos.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Diese App benötigt Galerie-Zugriff zum Auswählen von Fotos.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Diese App speichert Fotos in deiner Galerie.</string>
⚠️ Android Permissions: Ab Android 13 (API Level 33) sind READ_MEDIA_IMAGES und READ_MEDIA_VIDEO statt READ_EXTERNAL_STORAGE erforderlich. Claude Code generiert automatisch die korrekten Permission-Deklarationen basierend auf deiner Ziel-API-Version.
3. Push Notifications: Firebase & APNS
Push
Push Notifications sind für moderne Mobile-Apps unverzichtbar. Capacitor abstrahiert die Unterschiede zwischen Firebase Cloud Messaging (Android) und Apple Push Notification Service (iOS) hinter einer einheitlichen API.
# Push Notifications Plugin installieren
npm install @capacitor/push-notifications
npx cap sync
push-notifications.service.ts:
import { PushNotifications, PushNotificationSchema, Token, ActionPerformed } from '@capacitor/push-notifications';
import { Capacitor } from '@capacitor/core';
export class PushNotificationService {
async initialize(): Promise<void> {
if (!Capacitor.isNativePlatform()) {
console.log('Push Notifications nur auf nativen Plattformen verfügbar');
return;
}
// Permission anfragen
const permStatus = await PushNotifications.requestPermissions();
if (permStatus.receive === 'granted') {
await PushNotifications.register();
} else {
console.warn('Push Notification Permission verweigert');
return;
}
// Token empfangen (FCM Token für Android, APNS Token für iOS)
PushNotifications.addListener('registration', (token: Token) => {
console.log('Push Registration Token:', token.value);
this.sendTokenToBackend(token.value);
});
// Registration-Fehler behandeln
PushNotifications.addListener('registrationError', (error) => {
console.error('Push Registration Fehler:', error);
});
// Empfangene Notifications (App im Vordergrund)
PushNotifications.addListener('pushNotificationReceived',
(notification: PushNotificationSchema) => {
console.log('Notification empfangen:', notification.title, notification.body);
this.handleForegroundNotification(notification);
}
);
// Notification angeklickt (App im Hintergrund oder geschlossen)
PushNotifications.addListener('pushNotificationActionPerformed',
(action: ActionPerformed) => {
console.log('Notification Action:', action.actionId, action.notification.data);
this.handleNotificationTap(action);
}
);
}
private async sendTokenToBackend(token: string): Promise<void> {
await fetch('/api/push-tokens', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token,
platform: Capacitor.getPlatform(),
userId: this.getCurrentUserId(),
}),
});
}
private handleForegroundNotification(notification: PushNotificationSchema): void {
// In-App Banner anzeigen
const event = new CustomEvent('push-notification', { detail: notification });
document.dispatchEvent(event);
}
private handleNotificationTap(action: ActionPerformed): void {
const data = action.notification.data;
if (data?.route) {
// Navigation zu Deep-Link-Route
window.location.hash = data.route;
}
}
private getCurrentUserId(): string {
return localStorage.getItem('userId') ?? 'anonymous';
}
async removeAllListeners(): Promise<void> {
await PushNotifications.removeAllListeners();
}
}
Firebase-Konfiguration für Android: Lade google-services.json aus der Firebase Console herunter und platziere die Datei in android/app/. Für iOS benötigst du GoogleService-Info.plist in ios/App/App/.
# android/app/build.gradle — Firebase einbinden
apply plugin: 'com.google.gms.google-services'
dependencies {
implementation platform('com.google.firebase:firebase-bom:32.7.0')
implementation 'com.google.firebase:firebase-messaging'
}
💡 APNS Zertifikate (iOS): Im Apple Developer Portal benötigst du ein APNs Authentication Key (empfohlen) oder ein APNs-Zertifikat. Claude Code führt dich Schritt für Schritt durch den Prozess — inklusive der korrekten Konfiguration in Xcode Signing & Capabilities.
4. Biometrie & Secure Storage
Sicherheit
Biometrische Authentifizierung (Face ID, Touch ID, Fingerprint) und sicheres Speichern sensibler Daten sind in modernen Apps Standard. Capacitor-Plugins kapseln die plattformspezifischen Keychain- und Keystore-APIs.
# Biometrie & Secure Storage Plugins
npm install @capawesome-team/capacitor-biometrics
npm install @aparajita/capacitor-secure-storage
npm install @capacitor/preferences
npx cap sync
biometric-auth.service.ts — Face ID, Touch ID & Fingerprint:
import { Biometrics, BiometryType } from '@capawesome-team/capacitor-biometrics';
import { SecureStorage } from '@aparajita/capacitor-secure-storage';
import { Preferences } from '@capacitor/preferences';
interface BiometricResult {
success: boolean;
error?: string;
biometryType?: BiometryType;
}
export class BiometricAuthService {
async isAvailable(): Promise<boolean> {
try {
const result = await Biometrics.isBiometryAvailable();
return result.isAvailable;
} catch {
return false;
}
}
async getBiometryType(): Promise<BiometryType | null> {
try {
const result = await Biometrics.getBiometryType();
return result.biometryType;
} catch {
return null;
}
}
async authenticate(reason: string): Promise<BiometricResult> {
try {
const isAvailable = await this.isAvailable();
if (!isAvailable) {
return { success: false, error: 'Biometrie nicht verfügbar' };
}
await Biometrics.authenticate({
reason,
cancelTitle: 'Abbrechen',
allowDeviceCredential: true, // Fallback auf PIN/Passwort
});
return { success: true };
} catch (error: any) {
return {
success: false,
error: error.message ?? 'Authentifizierung fehlgeschlagen',
};
}
}
// Sicheres Speichern in iOS Keychain / Android Keystore
async saveSecretSecurely(key: string, value: string): Promise<void> {
await SecureStorage.set(key, value, true); // true = synchronize to iCloud Keychain
}
async getSecretSecurely(key: string): Promise<string | null> {
try {
const result = await SecureStorage.get(key, true);
return result?.value ?? null;
} catch {
return null;
}
}
// Auth-Token nach Biometrie-Prüfung laden
async getAuthTokenWithBiometrics(): Promise<string | null> {
const result = await this.authenticate('Authentifiziere dich für den Zugriff auf dein Konto');
if (!result.success) {
console.error('Biometrie-Authentifizierung fehlgeschlagen:', result.error);
return null;
}
return this.getSecretSecurely('auth_token');
}
// Preferences (nicht-sensitiv, für App-Settings)
async saveSetting(key: string, value: string): Promise<void> {
await Preferences.set({ key, value });
}
async getSetting(key: string): Promise<string | null> {
const { value } = await Preferences.get({ key });
return value;
}
}
⚠️ Sicherheitshinweis: Nutze SecureStorage (Keychain/Keystore) für alle sensitiven Daten wie Auth-Tokens, API-Keys oder persönliche Daten. Preferences (AsyncStorage-basiert) ist für nicht-sensitive App-Einstellungen gedacht und nicht verschlüsselt.
5. Live Updates & OTA Deployment
OTA
Over-the-Air (OTA) Updates ermöglichen es, den Web-Layer deiner App zu aktualisieren, ohne eine neue Version durch den App Store Review-Prozess zu schicken. Capawesome Live Updates ist die führende Lösung für Capacitor.
# Capawesome Live Updates Plugin
npm install @capawesome/capacitor-live-update
npx cap sync
live-update.service.ts — OTA Update Management:
import { LiveUpdate } from '@capawesome/capacitor-live-update';
import { App } from '@capacitor/app';
interface UpdateConfig {
channel: string;
autoDownload: boolean;
resetOnNewBundle: boolean;
}
export class LiveUpdateService {
private config: UpdateConfig = {
channel: 'production',
autoDownload: true,
resetOnNewBundle: false,
};
async initialize(): Promise<void> {
// Beim App-Start auf Updates prüfen
App.addListener('appStateChange', async ({ isActive }) => {
if (isActive) {
await this.checkForUpdates();
}
});
}
async checkForUpdates(): Promise<boolean> {
try {
const result = await LiveUpdate.getLatestBundle({
channel: this.config.channel,
});
if (!result.bundleId) {
console.log('Kein neues Update verfügbar');
return false;
}
console.log('Neues Bundle verfügbar:', result.bundleId);
if (this.config.autoDownload) {
await this.downloadAndApply(result.bundleId);
}
return true;
} catch (error) {
console.error('Update-Check fehlgeschlagen:', error);
return false;
}
}
async downloadAndApply(bundleId: string): Promise<void> {
try {
// Bundle herunterladen
await LiveUpdate.downloadBundle({ bundleId });
console.log('Bundle heruntergeladen:', bundleId);
// Bundle als nächstes aktives setzen
await LiveUpdate.setNextBundle({ bundleId });
console.log('Bundle als nächstes gesetzt');
// App neu laden (beim nächsten Start aktiv)
if (this.config.resetOnNewBundle) {
await LiveUpdate.reload();
}
} catch (error) {
console.error('Bundle-Download fehlgeschlagen:', error);
await this.rollback();
}
}
async rollback(): Promise<void> {
try {
await LiveUpdate.reset(); // Zurück zum eingebetteten Bundle
console.log('Rollback erfolgreich');
} catch (error) {
console.error('Rollback fehlgeschlagen:', error);
}
}
async getCurrentBundleVersion(): Promise<string> {
const result = await LiveUpdate.getCurrentBundle();
return result.bundleId ?? 'built-in';
}
async setChannel(channel: 'production' | 'staging' | 'beta'): Promise<void> {
this.config.channel = channel;
console.log('Update-Channel gesetzt:', channel);
}
}
Live Updates per CI/CD-Pipeline deployen:
# .github/workflows/live-update.yml
name: Live Update Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install & Build
run: |
npm ci
npm run build
- name: Deploy Live Update
run: |
npx @capawesome/cli live-update deploy \
--channel production \
--artifacts dist/ \
--token ${{ secrets.CAPAWESOME_TOKEN }}
💡 Richtlinien beachten: Apple und Google erlauben OTA-Updates nur für den Web-Layer (JavaScript, HTML, CSS, Assets). Änderungen am nativen Code (neue Plugins, Permissions) erfordern immer eine neue App-Version durch den Review-Prozess.
6. App Store Deployment: iOS & Android
Deploy
Der finale Schritt: Deine App in den App Store (iOS) und Google Play Store (Android) bringen. Claude Code führt dich durch die Signing-Konfiguration, das Erstellen von Builds und den Submission-Prozess.
iOS: Archive & TestFlight
# iOS Release Build vorbereiten
npm run build
npx cap sync ios
# In Xcode: Product → Archive → Distribute App
# Oder via Fastlane (empfohlen für CI/CD):
gem install fastlane
# fastlane/Fastfile
lane :beta do
increment_build_number
build_app(scheme: "App")
upload_to_testflight(
skip_waiting_for_build_processing: true,
api_key_path: "fastlane/api_key.json"
)
end
lane :release do
increment_version_number(version_number: "2.1.0")
increment_build_number
build_app(scheme: "App")
upload_to_app_store(
submit_for_review: true,
automatic_release: false
)
end
iOS App Review Checklist:
- App Store Connect: App ID, Bundle ID, Capabilities konfiguriert
- Provisioning Profile: Distribution Certificate gültig (1 Jahr)
- Privacy Manifest (
PrivacyInfo.xcprivacy): Alle API-Zugriffstypen deklariert
- Screenshots: 6.7" iPhone + 12.9" iPad in App Store Connect hochgeladen
- App Privacy: Datenschutz-Fragebogen vollständig ausgefüllt
- Export Compliance: Kryptographie-Nutzung deklariert (auch HTTPS)
- Review Notes: Test-Credentials für Review-Team bereitgestellt
Android: AAB & Google Play Console
# Android Release Build (AAB — bevorzugt für Play Store)
npm run build
npx cap sync android
# In Android Studio: Build → Generate Signed Bundle/APK
# Oder via Gradle CLI:
cd android
./gradlew bundleRelease
# APK signieren (falls nicht über Android Studio)
jarsigner -verbose \
-sigalg SHA256withRSA \
-digestalg SHA-256 \
-keystore my-release-key.jks \
app/build/outputs/bundle/release/app-release.aab \
my-key-alias
# Mit zipalign optimieren
zipalign -v 4 app-release.aab app-release-aligned.aab
# android/app/build.gradle — Signing-Konfiguration
android {
signingConfigs {
release {
storeFile file(System.getenv('KEYSTORE_PATH'))
storePassword System.getenv('KEYSTORE_PASSWORD')
keyAlias System.getenv('KEY_ALIAS')
keyPassword System.getenv('KEY_PASSWORD')
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Google Play Release Tracks:
Internal Testing
Bis 100 Tester, sofort verfügbar, kein Review
Closed Testing (Alpha)
Definierte Testergruppen, schneller Review
Open Testing (Beta)
Öffentlich, Opt-in, vor Production-Review
Production
Gestaffelter Rollout 1% → 10% → 50% → 100%
⚠️ Keystore-Backup ist kritisch: Verlierst du deinen Android Keystore, kannst du KEINE Updates mehr für deine App veröffentlichen — die App muss neu eingereicht werden und verliert alle Bewertungen und Downloads. Keystore-Datei + Passwörter sicher und redundant aufbewahren (z. B. verschlüsseltes Backup in Cloud-Speicher).
Fazit: Capacitor + Claude Code = Mobile Development im Turbogang
Capacitor.js hat die Cross-Platform Mobile-Entwicklung demokratisiert. Mit deinen Web-Kenntnissen (TypeScript, React, Vue) erstellst du native iOS- und Android-Apps mit vollem Zugriff auf alle nativen APIs — ohne Swift oder Kotlin lernen zu müssen.
Claude Code beschleunigt diesen Prozess in jeder Phase:
- Setup: Plugin-Konfiguration, Permissions, native Projekt-Struktur
- Native APIs: TypeScript-Service-Klassen für Camera, Filesystem, Geolocation
- Push & Auth: Firebase-Integration, APNS-Setup, Biometrie-Flows
- OTA Updates: Live Update-Strategien, Channel-Management, Rollback
- Deployment: Fastlane-Konfiguration, Signing, App Store Submission
- Debugging: Xcode/ADB Logs analysieren, native Bridge-Fehler aufklären
Das Ergebnis: Mobile-Apps, die sich nativ anfühlen, in der Hälfte der Entwicklungszeit — und ein einziger TypeScript-Codebase für iOS, Android und Web.
Mobile-Modul im Kurs
Im Claude Code Mastery Kurs: vollständiges Capacitor-Modul mit Native APIs, Push Notifications, Biometrie, Live Updates und App Store Deployment für iOS & Android.
14 Tage kostenlos testen →
AM
Agentic Movers Team
Wir helfen Entwicklern und Teams, mit Claude Code schneller bessere Software zu bauen — von Web-Apps bis zu nativen Mobile-Apps.