# Mobile App Best Practices for Future Implementation
## React Native Implementation Readiness Guide

---

## Overview

This document outlines best practices, architectural patterns, and implementation guidelines for building the native mobile apps (iOS & Android) using React Native. The current web implementation provides a solid foundation that can be leveraged for the mobile apps.

### Current Implementation Status
- ✅ **Web App (maternal-web)**: Fully implemented with Next.js 14
- ✅ **Backend API (maternal-app-backend)**: Complete with REST + WebSocket
- ⏳ **Mobile Apps**: Not yet implemented (planned)

### Technology Stack for Mobile

```javascript
{
  "react-native": "^0.73.0",
  "expo": "~50.0.0",
  "@react-navigation/native": "^6.1.0",
  "@react-navigation/stack": "^6.3.0",
  "react-native-paper": "^5.12.0",
  "redux-toolkit": "^2.0.0",
  "react-native-reanimated": "^3.6.0",
  "expo-secure-store": "~12.8.0",
  "expo-notifications": "~0.27.0"
}
```

---

## Architecture Principles

### 1. Code Reusability Between Web and Mobile

**Shared Business Logic**
```typescript
// ✅ GOOD: Platform-agnostic business logic
// libs/shared/src/services/activityService.ts
export class ActivityService {
  async logActivity(data: ActivityData): Promise<Activity> {
    // Platform-independent logic
    return this.apiClient.post('/activities', data);
  }
}

// Can be used in both web and mobile
```

**Platform-Specific UI**
```typescript
// ❌ BAD: Mixing UI and logic
function TrackingButton() {
  const [activity, setActivity] = useState();
  // Business logic mixed with UI
}

// ✅ GOOD: Separate concerns
// hooks/useActivityTracking.ts
export function useActivityTracking() {
  // Reusable logic
}

// web/components/TrackingButton.tsx
// mobile/components/TrackingButton.tsx
// Different UI, same logic via hook
```

**Recommended Project Structure**
```
maternal-app-monorepo/
├── apps/
│   ├── web/                    # Next.js web app (existing)
│   ├── mobile/                 # React Native mobile app (future)
│   └── backend/                # NestJS API (existing)
├── packages/
│   ├── shared/                 # Shared between web & mobile
│   │   ├── api-client/         # API communication
│   │   ├── state/              # Redux store & slices
│   │   ├── hooks/              # Custom React hooks
│   │   ├── utils/              # Utilities
│   │   └── types/              # TypeScript definitions
│   ├── ui-components/          # Platform-specific UI
│   │   ├── web/
│   │   └── mobile/
│   └── constants/              # Shared constants
└── tools/                      # Build tools & scripts
```

---

## Mobile-Specific Features

### 1. Offline-First Architecture

**Local Database: SQLite**
```typescript
// Mobile: Use SQLite for offline storage
import * as SQLite from 'expo-sqlite';

const db = SQLite.openDatabase('maternal.db');

// Sync queue for offline operations
interface SyncQueueItem {
  id: string;
  operation: 'CREATE' | 'UPDATE' | 'DELETE';
  entity: 'activity' | 'child' | 'family';
  data: any;
  timestamp: Date;
  retryCount: number;
}

// Auto-sync when connection restored
export class OfflineSyncService {
  async syncPendingChanges() {
    const pendingItems = await this.getSyncQueue();

    for (const item of pendingItems) {
      try {
        await this.syncItem(item);
        await this.removefromQueue(item.id);
      } catch (error) {
        await this.incrementRetryCount(item.id);
      }
    }
  }
}
```

**Conflict Resolution**
```typescript
// Last-write-wins with timestamp comparison
export class ConflictResolver {
  resolve(local: Activity, remote: Activity): Activity {
    const localTime = new Date(local.updatedAt);
    const remoteTime = new Date(remote.updatedAt);

    // Use latest version
    return localTime > remoteTime ? local : remote;
  }
}
```

### 2. Push Notifications

**Expo Notifications Setup**
```typescript
import * as Notifications from 'expo-notifications';
import * as Device from 'expo-device';

export class NotificationService {
  async registerForPushNotifications() {
    if (!Device.isDevice) {
      return null;
    }

    const { status: existingStatus } =
      await Notifications.getPermissionsAsync();

    let finalStatus = existingStatus;

    if (existingStatus !== 'granted') {
      const { status } =
        await Notifications.requestPermissionsAsync();
      finalStatus = status;
    }

    if (finalStatus !== 'granted') {
      return null;
    }

    const token = (
      await Notifications.getExpoPushTokenAsync({
        projectId: 'your-expo-project-id'
      })
    ).data;

    // Send token to backend
    await this.apiClient.post('/users/push-token', { token });

    return token;
  }

  // Configure notification behavior
  configureNotifications() {
    Notifications.setNotificationHandler({
      handleNotification: async () => ({
        shouldShowAlert: true,
        shouldPlaySound: true,
        shouldSetBadge: true,
      }),
    });
  }
}
```

**Notification Categories**
```typescript
// Backend: Define notification types
export enum NotificationType {
  FAMILY_UPDATE = 'family_update',
  ACTIVITY_REMINDER = 'activity_reminder',
  MILESTONE_REACHED = 'milestone_reached',
  AI_INSIGHT = 'ai_insight',
  SYNC_COMPLETE = 'sync_complete',
}

// Mobile: Handle notification tap
Notifications.addNotificationResponseReceivedListener(response => {
  const { type, data } = response.notification.request.content;

  switch (type) {
    case NotificationType.FAMILY_UPDATE:
      navigation.navigate('Family', { familyId: data.familyId });
      break;
    case NotificationType.ACTIVITY_REMINDER:
      navigation.navigate('Track', { type: data.activityType });
      break;
    // ... handle other types
  }
});
```

### 3. Biometric Authentication

**Face ID / Touch ID / Fingerprint**
```typescript
import * as LocalAuthentication from 'expo-local-authentication';
import * as SecureStore from 'expo-secure-store';

export class BiometricAuthService {
  async isBiometricAvailable(): Promise<boolean> {
    const compatible = await LocalAuthentication.hasHardwareAsync();
    const enrolled = await LocalAuthentication.isEnrolledAsync();
    return compatible && enrolled;
  }

  async authenticateWithBiometrics(): Promise<boolean> {
    const result = await LocalAuthentication.authenticateAsync({
      promptMessage: 'Authenticate to access Maternal App',
      fallbackLabel: 'Use passcode',
    });

    return result.success;
  }

  async enableBiometricLogin(userId: string, token: string) {
    // Store refresh token securely
    await SecureStore.setItemAsync(
      `auth_token_${userId}`,
      token,
      {
        keychainAccessible:
          SecureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
      }
    );

    // Enable biometric flag
    await SecureStore.setItemAsync(
      'biometric_enabled',
      'true'
    );
  }

  async loginWithBiometrics(): Promise<string | null> {
    const authenticated = await this.authenticateWithBiometrics();

    if (!authenticated) {
      return null;
    }

    // Retrieve stored token
    const userId = await SecureStore.getItemAsync('current_user_id');
    const token = await SecureStore.getItemAsync(`auth_token_${userId}`);

    return token;
  }
}
```

### 4. Voice Input (Whisper)

**React Native Voice**
```typescript
import Voice from '@react-native-voice/voice';

export class VoiceInputService {
  constructor() {
    Voice.onSpeechResults = this.onSpeechResults;
    Voice.onSpeechError = this.onSpeechError;
  }

  async startListening() {
    try {
      await Voice.start('en-US');
    } catch (error) {
      console.error('Voice start error:', error);
    }
  }

  async stopListening() {
    try {
      await Voice.stop();
    } catch (error) {
      console.error('Voice stop error:', error);
    }
  }

  onSpeechResults = (event: any) => {
    const transcript = event.value[0];
    // Send to backend for processing with Whisper
    this.processTranscript(transcript);
  };

  onSpeechError = (event: any) => {
    console.error('Speech error:', event.error);
  };

  async processTranscript(transcript: string) {
    // Send to backend Whisper API
    const response = await fetch('/api/v1/voice/transcribe', {
      method: 'POST',
      body: JSON.stringify({ transcript }),
    });

    const { activityData } = await response.json();
    return activityData;
  }
}
```

### 5. Camera & Photo Upload

**Expo Image Picker**
```typescript
import * as ImagePicker from 'expo-image-picker';

export class PhotoService {
  async requestPermissions() {
    const { status } =
      await ImagePicker.requestMediaLibraryPermissionsAsync();

    if (status !== 'granted') {
      Alert.alert(
        'Permission needed',
        'Please allow access to photos'
      );
      return false;
    }

    return true;
  }

  async pickImage() {
    const hasPermission = await this.requestPermissions();
    if (!hasPermission) return null;

    const result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.Images,
      allowsEditing: true,
      aspect: [4, 3],
      quality: 0.8,
    });

    if (!result.canceled) {
      return result.assets[0].uri;
    }

    return null;
  }

  async takePhoto() {
    const { status } =
      await ImagePicker.requestCameraPermissionsAsync();

    if (status !== 'granted') {
      return null;
    }

    const result = await ImagePicker.launchCameraAsync({
      allowsEditing: true,
      aspect: [4, 3],
      quality: 0.8,
    });

    if (!result.canceled) {
      return result.assets[0].uri;
    }

    return null;
  }

  async uploadPhoto(uri: string, childId: string) {
    const formData = new FormData();
    formData.append('file', {
      uri,
      type: 'image/jpeg',
      name: 'photo.jpg',
    } as any);
    formData.append('childId', childId);

    const response = await fetch('/api/v1/children/photo', {
      method: 'POST',
      body: formData,
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    });

    return response.json();
  }
}
```

---

## Performance Optimization

### 1. List Virtualization

**FlatList for Large Datasets**
```typescript
import { FlatList } from 'react-native';

// ✅ GOOD: Virtualized list for activities
<FlatList
  data={activities}
  renderItem={({ item }) => <ActivityCard activity={item} />}
  keyExtractor={(item) => item.id}

  // Performance optimizations
  removeClippedSubviews={true}
  maxToRenderPerBatch={10}
  updateCellsBatchingPeriod={50}
  initialNumToRender={10}
  windowSize={5}

  // Pull to refresh
  onRefresh={handleRefresh}
  refreshing={isRefreshing}

  // Infinite scroll
  onEndReached={loadMore}
  onEndReachedThreshold={0.5}
/>

// ❌ BAD: Rendering all items at once
{activities.map(activity => <ActivityCard key={activity.id} activity={activity} />)}
```

### 2. Image Optimization

**React Native Fast Image**
```typescript
import FastImage from 'react-native-fast-image';

// ✅ GOOD: Optimized image loading
<FastImage
  source={{
    uri: childPhoto,
    priority: FastImage.priority.high,
    cache: FastImage.cacheControl.immutable,
  }}
  style={styles.childPhoto}
  resizeMode={FastImage.resizeMode.cover}
/>

// Preload images for better UX
FastImage.preload([
  { uri: photo1 },
  { uri: photo2 },
]);
```

### 3. Animation Performance

**React Native Reanimated 3**
```typescript
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
} from 'react-native-reanimated';

// ✅ GOOD: Run on UI thread
function AnimatedButton() {
  const scale = useSharedValue(1);

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ scale: scale.value }],
  }));

  const handlePress = () => {
    scale.value = withSpring(0.95, {}, () => {
      scale.value = withSpring(1);
    });
  };

  return (
    <Animated.View style={animatedStyle}>
      <TouchableOpacity onPress={handlePress}>
        <Text>Track Activity</Text>
      </TouchableOpacity>
    </Animated.View>
  );
}
```

### 4. Bundle Size Optimization

**Hermes Engine (for Android)**
```javascript
// android/app/build.gradle
project.ext.react = [
  enableHermes: true,  // Enable Hermes engine
]

// Results in:
// - Faster startup time
// - Lower memory usage
// - Smaller APK size
```

**Code Splitting**
```typescript
// Lazy load heavy screens
const AIAssistant = lazy(() => import('./screens/AIAssistant'));
const Analytics = lazy(() => import('./screens/Analytics'));

// Use with Suspense
<Suspense fallback={<LoadingSpinner />}>
  <AIAssistant />
</Suspense>
```

---

## Testing Strategy for Mobile

### Unit Tests (Jest)
```typescript
import { renderHook, act } from '@testing-library/react-hooks';
import { useActivityTracking } from './useActivityTracking';

describe('useActivityTracking', () => {
  it('should track activity successfully', async () => {
    const { result } = renderHook(() => useActivityTracking());

    await act(async () => {
      await result.current.logActivity({
        type: 'feeding',
        childId: 'child_123',
      });
    });

    expect(result.current.activities).toHaveLength(1);
  });
});
```

### Component Tests (React Native Testing Library)
```typescript
import { render, fireEvent } from '@testing-library/react-native';
import { TrackingButton } from './TrackingButton';

describe('TrackingButton', () => {
  it('should handle press event', () => {
    const onPress = jest.fn();
    const { getByText } = render(
      <TrackingButton onPress={onPress} />
    );

    fireEvent.press(getByText('Track Feeding'));
    expect(onPress).toHaveBeenCalled();
  });
});
```

### E2E Tests (Detox)
```typescript
describe('Activity Tracking Flow', () => {
  beforeAll(async () => {
    await device.launchApp();
  });

  it('should log a feeding activity', async () => {
    await element(by.id('track-feeding-btn')).tap();
    await element(by.id('amount-input')).typeText('120');
    await element(by.id('save-btn')).tap();

    await expect(element(by.text('Activity saved'))).toBeVisible();
  });
});
```

---

## Platform-Specific Considerations

### iOS Specific

**1. App Store Guidelines**
```markdown
- ✅ Submit privacy manifest (PrivacyInfo.xcprivacy)
- ✅ Declare data collection practices
- ✅ Request permissions with clear explanations
- ✅ Support all device sizes (iPhone, iPad)
- ✅ Dark mode support required
```

**2. iOS Permissions**
```xml
<!-- ios/maternal/Info.plist -->
<key>NSCameraUsageDescription</key>
<string>Take photos of your child's milestones</string>

<key>NSPhotoLibraryUsageDescription</key>
<string>Save and view photos of your child</string>

<key>NSMicrophoneUsageDescription</key>
<string>Use voice to log activities hands-free</string>

<key>NSFaceIDUsageDescription</key>
<string>Use Face ID for quick and secure login</string>
```

**3. iOS Background Modes**
```xml
<key>UIBackgroundModes</key>
<array>
  <string>remote-notification</string>
  <string>fetch</string>
</array>
```

### Android Specific

**1. Permissions**
```xml
<!-- android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
```

**2. ProGuard (Code Obfuscation)**
```
# android/app/proguard-rules.pro
-keep class com.maternalapp.** { *; }
-keepclassmembers class * {
  @com.facebook.react.uimanager.annotations.ReactProp <methods>;
}
```

**3. App Signing**
```bash
# Generate release keystore
keytool -genkeypair -v -storetype PKCS12 \
  -keystore maternal-app-release.keystore \
  -alias maternal-app \
  -keyalg RSA -keysize 2048 \
  -validity 10000
```

---

## Deployment & Distribution

### App Store (iOS)

**1. Build Configuration**
```bash
# Install dependencies
cd ios && pod install

# Build for production
xcodebuild -workspace MaternalApp.xcworkspace \
  -scheme MaternalApp \
  -configuration Release \
  -archivePath MaternalApp.xcarchive \
  archive

# Export IPA
xcodebuild -exportArchive \
  -archivePath MaternalApp.xcarchive \
  -exportPath ./build \
  -exportOptionsPlist ExportOptions.plist
```

**2. TestFlight (Beta Testing)**
```bash
# Upload to TestFlight
xcrun altool --upload-app \
  --type ios \
  --file MaternalApp.ipa \
  --username "developer@example.com" \
  --password "@keychain:AC_PASSWORD"
```

### Google Play (Android)

**1. Build AAB (Android App Bundle)**
```bash
cd android
./gradlew bundleRelease

# Output: android/app/build/outputs/bundle/release/app-release.aab
```

**2. Internal Testing Track**
```bash
# Upload to Google Play Console
# Use Fastlane or manual upload
```

### Over-the-Air Updates (CodePush)

**Setup for rapid iteration**
```bash
# Install CodePush CLI
npm install -g code-push-cli

# Register app
code-push app add maternal-app-ios ios react-native
code-push app add maternal-app-android android react-native

# Release update
code-push release-react maternal-app-ios ios \
  -d Production \
  --description "Bug fixes and performance improvements"
```

**Rollback Strategy**
```bash
# Rollback to previous version if issues detected
code-push rollback maternal-app-ios Production

# Monitor adoption rate
code-push deployment ls maternal-app-ios
```

---

## Monitoring & Analytics

### Crash Reporting (Sentry)
```typescript
import * as Sentry from '@sentry/react-native';

Sentry.init({
  dsn: 'YOUR_SENTRY_DSN',
  environment: __DEV__ ? 'development' : 'production',
  tracesSampleRate: 1.0,
});

// Automatic breadcrumbs
Sentry.addBreadcrumb({
  category: 'activity',
  message: 'User logged feeding activity',
  level: 'info',
});

// Custom error context
Sentry.setContext('user', {
  id: user.id,
  familyId: family.id,
});
```

### Performance Monitoring
```typescript
import * as Sentry from '@sentry/react-native';

// Monitor screen load time
const transaction = Sentry.startTransaction({
  name: 'ActivityTrackingScreen',
  op: 'navigation',
});

// ... screen loads ...

transaction.finish();

// Monitor specific operations
const span = transaction.startChild({
  op: 'api.call',
  description: 'Log activity',
});

await logActivity(data);
span.finish();
```

### Usage Analytics
```typescript
// Integrate with backend analytics service
import { Analytics } from '@maternal/shared/analytics';

Analytics.track('Activity Logged', {
  type: 'feeding',
  method: 'voice',
  duration: 15000,
});

Analytics.screen('Activity Tracking');

Analytics.identify(user.id, {
  familySize: family.members.length,
  childrenCount: children.length,
  isPremium: subscription.isPremium,
});
```

---

## Accessibility (WCAG AA Compliance)

### Screen Reader Support
```typescript
import { View, Text, TouchableOpacity } from 'react-native';

<TouchableOpacity
  accessible={true}
  accessibilityLabel="Log feeding activity"
  accessibilityHint="Opens feeding activity tracker"
  accessibilityRole="button"
  onPress={handlePress}
>
  <Text>Track Feeding</Text>
</TouchableOpacity>
```

### Dynamic Font Sizes
```typescript
import { Text, useWindowDimensions } from 'react-native';

// Respect user's font size preferences
<Text
  style={{
    fontSize: 16,
    lineHeight: 24,
  }}
  allowFontScaling={true}
  maxFontSizeMultiplier={2}
>
  Activity logged successfully
</Text>
```

### Color Contrast
```typescript
// Ensure WCAG AA compliance (4.5:1 ratio for normal text)
const colors = {
  primary: '#FF8B7D',      // Coral
  primaryText: '#1A1A1A',  // Dark text on light background
  background: '#FFFFFF',
  textOnPrimary: '#FFFFFF', // White text on coral
};

// Validate contrast ratios in design system
```

---

## Security Best Practices

### Secure Storage
```typescript
import * as SecureStore from 'expo-secure-store';

// ✅ GOOD: Encrypted storage for sensitive data
await SecureStore.setItemAsync('auth_token', token);

// ❌ BAD: AsyncStorage for sensitive data (unencrypted)
await AsyncStorage.setItem('auth_token', token);
```

### Certificate Pinning
```typescript
// Prevent man-in-the-middle attacks
import { configureCertificatePinning } from 'react-native-cert-pinner';

await configureCertificatePinning([
  {
    hostname: 'api.maternalapp.com',
    certificates: [
      'sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=',
    ],
  },
]);
```

### Jailbreak/Root Detection
```typescript
import JailMonkey from 'jail-monkey';

if (JailMonkey.isJailBroken()) {
  Alert.alert(
    'Security Warning',
    'This app may not function properly on jailbroken devices'
  );
}
```

---

## Migration Path from Web to Mobile

### Phase 1: Extract Shared Logic
```typescript
// 1. Move business logic to shared package
// packages/shared/src/services/
export class ActivityService { ... }
export class AIService { ... }

// 2. Update web app to use shared package
import { ActivityService } from '@maternal/shared';
```

### Phase 2: Build Mobile Shell
```typescript
// 1. Create React Native app with Expo
npx create-expo-app maternal-mobile

// 2. Set up navigation structure
// 3. Integrate shared services
// 4. Build basic UI with React Native Paper
```

### Phase 3: Implement Mobile-Specific Features
```typescript
// 1. Offline mode with SQLite
// 2. Push notifications
// 3. Biometric auth
// 4. Voice input
// 5. Camera integration
```

### Phase 4: Testing & Optimization
```typescript
// 1. Unit tests
// 2. Component tests
// 3. E2E tests with Detox
// 4. Performance profiling
// 5. Accessibility audit
```

### Phase 5: Beta Testing & Launch
```typescript
// 1. TestFlight (iOS)
// 2. Google Play Internal Testing
// 3. Gather feedback
// 4. Iterate based on metrics
// 5. Production launch
```

---

## Conclusion

This guide provides a comprehensive roadmap for implementing native mobile apps. Key takeaways:

1. **Code Reusability**: Share business logic between web and mobile
2. **Offline-First**: Essential for mobile UX
3. **Native Features**: Leverage platform-specific capabilities
4. **Performance**: Optimize for mobile constraints
5. **Testing**: Comprehensive strategy for quality
6. **Security**: Protect user data on mobile devices
7. **Analytics**: Track usage and iterate

The current web implementation already follows many mobile-friendly patterns, making the transition to React Native straightforward when the time comes.
