Architecture Patterns
Service Layer
All business logic is abstracted into dedicated service modules, keeping components clean and testable.
FoodAnalysisService.ts
Purpose: AI-powered food recognition and nutritional analysis
Key Functions:
analyzeFood(imageUri: string): Promise<FoodAnalysisResult>
getNutritionalData(foodName: string): Promise<NutritionData>
searchFoodDatabase(query: string): Promise<FoodItem[]>Responsibilities:
- Upload photos to storage
- Send images to OpenAI Vision API
- Parse AI responses
- Extract nutritional information
- Query food database
- Cache results for performance
WorkoutAnalysisService.ts
Purpose: Exercise recognition and calorie burn calculations
Key Functions:
analyzeWorkout(imageUri: string): Promise<WorkoutAnalysisResult>
calculateCaloriesBurned(exercise, duration, weight): number
getExerciseLibrary(): Promise<Exercise[]>Responsibilities:
- AI workout recognition from photos
- MET-based calorie calculations
- Exercise database integration
- Workout type classification
- Intensity estimation
HealthProfileService.ts
Purpose: User health data management and calculations
Key Functions:
getHealthProfile(userId: string): Promise<HealthProfile>
updateHealthProfile(userId, data): Promise<void>
calculateDailyCalories(profile): CalorieTargets
calculateBMI(weight, height): numberResponsibilities:
- Fetch and update health metrics
- BMR (Basal Metabolic Rate) calculation
- TDEE (Total Daily Energy Expenditure) calculation
- Goal-based calorie targets
- Macro distribution recommendations
SubscriptionService.ts
Purpose: Payment and subscription management
Key Functions:
checkSubscriptionStatus(userId): Promise<SubscriptionStatus>
getUsageStats(userId): Promise<UsageStats>
upgradeSubscription(userId, plan): Promise<CheckoutSession>
trackAPIUsage(userId): Promise<void>Responsibilities:
- Stripe payment integration
- RevenueCat subscription sync
- API usage tracking
- Limit enforcement
- Subscription state management
UserEntriesService.ts
Purpose: Food and workout log management
Key Functions:
addFoodEntry(userId, entry): Promise<EntryResult>
addWorkoutEntry(userId, entry): Promise<EntryResult>
getEntriesByDate(userId, date): Promise<DailyEntries>
updateEntry(entryId, data): Promise<void>
deleteEntry(entryId, type): Promise<void>Responsibilities:
- CRUD operations for entries
- Daily/weekly/monthly aggregations
- Entry validation
- Photo URL management
- Data consistency
supabase.ts
Purpose: Database and authentication operations
Key Functions:
createClient(): SupabaseClient
signIn(provider): Promise<AuthResult>
signOut(): Promise<void>
query(table, filters): Promise<QueryResult>
subscribe(table, callback): SubscriptionResponsibilities:
- Supabase client initialization
- Authentication flows
- Database queries
- Real-time subscriptions
- File storage operations
Context Providers
React Context API for global state management.
ThemeProvider
Purpose: Theme management and switching
State:
{
theme: 'light' | 'dark' | 'system',
colors: ColorScheme,
isDark: boolean
}Methods:
setTheme(theme)- Change themetoggleTheme()- Switch between light/darkgetColor(name)- Resolve theme-aware color
Features:
- Persists theme preference
- System theme detection
- Smooth transitions
- All components theme-aware
OnboardingProvider
Purpose: Onboarding flow state management
State:
{
currentStep: number,
data: OnboardingData,
isComplete: boolean
}Methods:
nextStep()- Move to next screenpreviousStep()- Go backupdateData(key, value)- Save step datasubmitOnboarding()- Complete flow
Features:
- Multi-step form handling
- Data validation per step
- Progress tracking
- Resume capability
PaymentsProvider
Purpose: Subscription and payment state
State:
{
subscriptionStatus: SubscriptionStatus,
usageStats: UsageStats,
isLoading: boolean
}Methods:
checkStatus()- Refresh subscriptionupgrade(plan)- Initiate purchasecancelSubscription()- End subscriptionrestorePurchases()- Restore on new device
Features:
- Real-time subscription sync
- Usage tracking
- Payment flow handling
- Receipt validation
AuthProvider
Purpose: Authentication state management
State:
{
user: User | null,
session: Session | null,
isAuthenticated: boolean,
isLoading: boolean
}Methods:
signIn(provider)- OAuth loginsignOut()- Logout userrefreshSession()- Token refreshupdateProfile(data)- Update user info
Features:
- Automatic token refresh
- Session persistence
- Multi-device support
- Secure token storage
Component Structure
Atomic Design Principles
Atoms (Basic UI Elements)
components/ui/
├── Button.tsx
├── Input.tsx
├── Text.tsx
├── Icon.tsx
├── Badge.tsx
└── Avatar.tsxCharacteristics:
- Single responsibility
- Highly reusable
- No business logic
- Theme-aware
- Accessible
Molecules (Simple Combinations)
components/
├── Card.tsx
├── ListItem.tsx
├── FormField.tsx
├── PostCard.tsx
└── StatCard.tsxCharacteristics:
- Combine atoms
- Specific purpose
- Reusable patterns
- Props-driven
- Composable
Organisms (Complex Sections)
components/
├── FoodPostCard.tsx
├── WorkoutPostCard.tsx
├── AnalyticsChart.tsx
├── OnboardingStep.tsx
└── NavigationBar.tsxCharacteristics:
- Complete UI sections
- May include business logic
- Context-aware
- Feature-specific
- Self-contained
Templates (Page Layouts)
components/layouts/
├── AuthLayout.tsx
├── MainLayout.tsx
├── OnboardingLayout.tsx
└── ModalLayout.tsxCharacteristics:
- Page structure
- Consistent layouts
- Navigation integration
- Header/footer management
Pages (Complete Screens)
app/(tabs)/
├── index.tsx
├── analytics.tsx
├── profile.tsx
└── add-post/Characteristics:
- Full screens
- Data fetching
- Route handling
- SEO/metadata
Type-Safe Props
Every component has TypeScript interfaces:
interface FoodPostCardProps {
post: FoodPost;
onLike?: () => void;
onComment?: () => void;
showActions?: boolean;
}
export function FoodPostCard({
post,
onLike,
onComment,
showActions = true
}: FoodPostCardProps) {
// Component implementation
}Benefits:
- Compile-time error checking
- IntelliSense support
- Self-documenting code
- Refactoring safety
Theme-Aware Styling
All components use theme-aware styles:
import { useTheme } from '@/contexts/ThemeProvider';
export function MyComponent() {
const { colors, isDark } = useTheme();
return (
<View style={{
backgroundColor: colors.background,
borderColor: colors.border
}}>
{/* Content */}
</View>
);
}Data Flow Patterns
Unidirectional Data Flow
User Action → Service Call → State Update → UI Re-renderOptimistic Updates
// Immediate UI update
setLocalState(newValue);
// Background sync
try {
await service.update(newValue);
} catch (error) {
// Revert on failure
setLocalState(oldValue);
showError();
}Real-Time Subscriptions
useEffect(() => {
const subscription = supabase
.from('food_entries')
.on('INSERT', handleNewEntry)
.on('UPDATE', handleUpdatedEntry)
.subscribe();
return () => subscription.unsubscribe();
}, []);Error Handling
Service Layer Errors
All services throw typed errors:
try {
const result = await FoodAnalysisService.analyzeFood(uri);
} catch (error) {
if (error.code === 'RATE_LIMIT_EXCEEDED') {
// Show upgrade prompt
} else if (error.code === 'NETWORK_ERROR') {
// Show retry
} else {
// Generic error
}
}Error Boundaries
React Error Boundaries catch component errors:
<ErrorBoundary fallback={<ErrorScreen />}>
<App />
</ErrorBoundary>Performance Optimizations
React.memo for Expensive Components
export const ExpensiveComponent = React.memo(
({ data }) => {
// Render logic
},
(prevProps, nextProps) => {
// Custom comparison
return prevProps.data.id === nextProps.data.id;
}
);useMemo for Expensive Calculations
const sortedData = useMemo(() => {
return data.sort((a, b) => a.calories - b.calories);
}, [data]);useCallback for Stable Function References
const handlePress = useCallback(() => {
doSomething(item.id);
}, [item.id]);FlatList for Long Lists
<FlatList
data={entries}
renderItem={renderEntry}
keyExtractor={(item) => item.id}
windowSize={10}
maxToRenderPerBatch={10}
removeClippedSubviews={true}
/>