ADR-004: Mobile App Architecture

Status: Proposed
Date: 2025-01-27
Deciders: Technical Architecture Team

Context

The documentation mentions a React Native mobile application with offline sync and push notifications, but this feature is not yet implemented. We need to decide on the mobile app architecture for the internal operations platform.

Business Context:

Current State:

Requirements:

Decision

Technology Stack: React Native with Expo
Architecture: Offline-first with real-time sync
Deployment: App Store and Google Play Store

Rationale:

Consequences

Positive:

Negative:

Implementation Plan

Phase 1: Basic Mobile App (4 weeks)

Phase 2: Offline Sync (2 weeks)

Phase 3: Native Features (2 weeks)

Phase 4: Production (2 weeks)

Technical Architecture

React Native with Expo

// App.tsx - Main application component
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

const Stack = createStackNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Dashboard" component={Dashboard} />
        <Stack.Screen name="Projects" component={Projects} />
        <Stack.Screen name="Settings" component={Settings} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Offline-First Architecture

// Offline data sync with Supabase
import { createClient } from '@supabase/supabase-js'
import AsyncStorage from '@react-native-async-storage/async-storage'

const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY)

const useOfflineSync = () => {
  const [isOnline, setIsOnline] = useState(true)
  const [pendingChanges, setPendingChanges] = useState([])

  useEffect(() => {
    // Check network status
    const unsubscribe = NetInfo.addEventListener((state) => {
      setIsOnline(state.isConnected)
    })

    return unsubscribe
  }, [])

  const syncData = async () => {
    if (isOnline) {
      // Sync pending changes
      for (const change of pendingChanges) {
        await supabase.from(change.table).upsert(change.data)
      }
      setPendingChanges([])
    }
  }

  return { isOnline, syncData }
}

Push Notifications

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

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: true,
    shouldSetBadge: false,
  }),
})

const registerForPushNotifications = async () => {
  const { status } = await Notifications.requestPermissionsAsync()

  if (status === 'granted') {
    const token = await Notifications.getExpoPushTokenAsync()
    // Send token to server for notifications
    return token
  }
}

Current Implementation Status

✅ IMPLEMENTED

❌ NOT IMPLEMENTED

Feature Specifications

Core Features

Native Features

User Experience

Development Considerations

Cross-Platform Development

Offline-First Design

Performance Optimization

Deployment Strategy

Development

Production

Security Considerations

Data Security

App Security

Future Enhancements

Advanced Features

Integration Features

Review

Next Review: 2025-04-27
Reviewers: Technical Architecture Team
Status: Proposed (awaiting implementation)


Document Version: 1.0
Last Updated: 2025-01-27
Owner: Technical Architecture Team