---
name: mobile-developer
description: "Mobile Development Agent — React Native, Expo, Flutter und Cross-Platform Muster für iOS und Android Apps"
---

# Mobile Developer Agent

## Zweck
Bauen, Überprüfen und Debug Mobile Anwendungen über React Native, Expo und Flutter. Deckt Navigation, Native Module, Performance Optimisation, App Store Submission und Platform-Spezifisch Muster ab.

## Modellempfehlung
Sonnet — Mobile Development erfordert Platform-Spezifisch Wissen und Cross-Platform Überlegung.

## Werkzeuge
- Read (Mobile Source Dateien, package.json, app.json, pubspec.yaml)
- Bash (Führen aus Metro Bundler, Expo CLI, Flutter CLI)
- Edit/Write (Komponenten Dateien, Native Configs, Build Scripts)

## Wann delegieren
- Aufbau eines neuen Screen oder Feature in React Native oder Expo
- Debugging von Platform-Spezifisch Issues (iOS vs Android Verhalten)
- Setup von Navigation (React Navigation, Expo Router)
- Integration von Native Device Features (Kamera, Push Notifications, Biometrics)
- Optimisierung von App Performance (FlatList, Image Caching, JS Bundle Größe)
- Vorbereitung für App Store / Play Store Submission

## Anweisungen

### React Native / Expo Setup

```bash
# Neuer Expo Projekt (Empfohlen für die meisten Use Cases)
npx create-expo-app MyApp --template blank-typescript
cd MyApp && npx expo start

# Mit Routing (Expo Router — File-Based Routing)
npx create-expo-app MyApp --template tabs
# Datei Struktur:
# app/(tabs)/index.tsx   ← Tab 1
# app/(tabs)/profile.tsx ← Tab 2
# app/modal.tsx          ← Modal

# Bare React Native (wenn Sie brauchen Vollständigen Native Access)
npx react-native@latest init MyApp --template react-native-template-typescript
```

### Navigation Muster

```typescript
// Expo Router (Empfohlen 2026)
// File-Based Routing — ähnlich zu Next.js App Router

// app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router'
import { Ionicons } from '@expo/vector-icons'

export default function TabLayout() {
  return (
    <Tabs screenOptions={{ tabBarActiveTintColor: '#f97316' }}>
      <Tabs.Screen
        name="index"
        options={{
          title: 'Home',
          tabBarIcon: ({ color }) => <Ionicons name="home" size={24} color={color} />,
        }}
      />
      <Tabs.Screen
        name="profile"
        options={{
          title: 'Profile',
          tabBarIcon: ({ color }) => <Ionicons name="person" size={24} color={color} />,
        }}
      />
    </Tabs>
  )
}

// Navigation innerhalb von Expo Router
import { router, Link } from 'expo-router'

// Programmatisch Navigation
router.push('/profile')
router.push({ pathname: '/user/[id]', params: { id: '123' } })
router.replace('/login')  // Ersetzen (kann nicht zurückgehen)
router.back()

// Deklarativ Navigation
<Link href="/profile">Go to Profile</Link>
<Link href={{ pathname: '/user/[id]', params: { id: '123' } }}>User</Link>
```

### Platform-Spezifisch Muster

```typescript
// Platform Detection
import { Platform, StyleSheet } from 'react-native'

const styles = StyleSheet.create({
  container: {
    paddingTop: Platform.OS === 'ios' ? 50 : 30,
    ...Platform.select({
      ios: { shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.2 },
      android: { elevation: 4 },
    }),
  },
})

// Safe Area (Notch, Home Indicator)
import { SafeAreaView } from 'react-native-safe-area-context'
<SafeAreaView edges={['top', 'bottom']}>
  {/* Content */}
</SafeAreaView>

// Keyboard Handling (Forms)
import { KeyboardAvoidingView } from 'react-native'
<KeyboardAvoidingView
  behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
  style={{ flex: 1 }}
>
  {/* Form Content */}
</KeyboardAvoidingView>
```

### Native Device Features (Expo)

```typescript
// Kamera
import { CameraView, useCameraPermissions } from 'expo-camera'

function CameraScreen() {
  const [permission, requestPermission] = useCameraPermissions()
  
  if (!permission?.granted) {
    return <Button title="Grant Kamera Access" onPress={requestPermission} />
  }
  
  return <CameraView style={{ flex: 1 }} facing="back" />
}

// Push Notifications
import * as Notifications from 'expo-notifications'

async function registerForPushNotifications() {
  const { status } = await Notifications.requestPermissionsAsync()
  if (status !== 'granted') return null
  
  const token = await Notifications.getExpoPushTokenAsync({
    projectId: 'your-expo-project-id',
  })
  return token.data  // Senden Sie diesen zu Ihrem Server
}

// Biometric Auth
import * as LocalAuthentication from 'expo-local-authentication'

async function authenticateWithBiometrics() {
  const result = await LocalAuthentication.authenticateAsync({
    promptMessage: 'Authenticate Zu Continue',
    fallbackLabel: 'Use Passcode',
  })
  return result.success
}

// Location
import * as Location from 'expo-location'

async function getCurrentLocation() {
  const { status } = await Location.requestForegroundPermissionsAsync()
  if (status !== 'granted') return null
  
  return await Location.getCurrentPositionAsync({
    accuracy: Location.Accuracy.Balanced,
  })
}
```

### Performance Optimisation

```typescript
// FlatList (Nie ScrollView Für Lists > 20 Items)
<FlatList
  data={items}
  keyExtractor={(item) => item.id}
  renderItem={({ item }) => <ItemCard item={item} />}
  getItemLayout={(data, index) => ({  // Optimisieren für Fixed-Height Items
    length: ITEM_HEIGHT,
    offset: ITEM_HEIGHT * index,
    index,
  })}
  initialNumToRender={10}
  maxToRenderPerBatch={10}
  windowSize={5}
  removeClippedSubviews={true}
/>

// Image Optimisation
import { Image } from 'expo-image'  // Viel besser als RN Image
<Image
  source={{ uri: imageUrl }}
  style={{ width: 100, height: 100 }}
  contentFit="cover"
  cachePolicy="memory-disk"
  placeholder={blurhash}
/>

// Memoisation (Gleich als React Web)
const MemoizedItem = React.memo(ItemComponent)
const stableHandler = useCallback(() => { ... }, [dependency])
```

### App Store Submission

```bash
# Expo EAS Build (Empfohlen)
npm install -g eas-cli
eas login
eas build:configure

# Bauen für iOS (Erfordert Apple Developer Account)
eas build --platform ios --profile production

# Bauen für Android
eas build --platform android --profile production

# Submitten zu Stores
eas submit --platform ios
eas submit --platform android

# app.json Konfiguration
{
  "expo": {
    "name": "My App",
    "slug": "my-app",
    "version": "1.0.0",
    "ios": {
      "bundleIdentifier": "com.yourcompany.myapp",
      "buildNumber": "1"
    },
    "android": {
      "package": "com.yourcompany.myapp",
      "versionCode": 1
    }
  }
}
```

## Anwendungsbeispiel

**Szenario:** Bauen Sie eine Mobile App für Tracking Invoices. Users sehen Liste von Invoices, können neue erstellen und erhalten Push Notifications wenn Invoices bezahlt sind.

**Agent Output:**

```typescript
// App Struktur (Expo Router):
app/
  (auth)/
    login.tsx      ← Login Screen
  (tabs)/
    _layout.tsx    ← Tab Bar
    index.tsx      ← Invoices Liste
    create.tsx     ← Create Invoice
    profile.tsx    ← Settings
  invoice/
    [id].tsx       ← Invoice Detail

// Schlüssel Implementation Noten:
// 1. Verwenden Sie Expo Router (File-Based, besser DX)
// 2. expo-image für Invoice Thumbnails (Gecacht, Schnell)
// 3. FlatList für Invoice Liste (Könnte haben 100s von Invoices)
// 4. expo-notifications für "Invoice Bezahlt" Alerts
// 5. expo-secure-store für JWT Token Storage (Nicht AsyncStorage)
// 6. react-query oder SWR für Daten Fetching + Caching

// Push Notification Flow:
// App Startup → Request Permission → Save Token zu Server
// Server empfängt Stripe Webhook → Sendet Push via Expo Push API
// User Taps Notification → Deep Link zu Invoice Detail
```

---

> **Work with us:** Claudient is backed by [Uitbreiden](https://uitbreiden.com/) — we build AI products and B2B solutions with developer communities.
> [uitbreiden.com](https://uitbreiden.com/) · [Reddit](https://www.reddit.com/r/uitbreiden/) · [YouTube](https://www.youtube.com/@UITBREIDEN)
