System Architecture - dinesh-git17/my-progress-planner GitHub Wiki
Deep dive into the technical architecture and design decisions behind My Progress Planner.
🏗️ High-Level Architecture
graph TB
subgraph "Client Layer"
A[Next.js Frontend]
B[Service Worker]
C[IndexedDB Cache]
end
subgraph "API Layer"
D[Next.js API Routes]
E[Authentication Middleware]
F[Rate Limiting]
end
subgraph "External Services"
G[Supabase Auth]
H[Supabase Database]
I[OpenAI GPT-4 API]
J[Push Notification Service]
end
subgraph "Infrastructure"
K[Vercel Edge Functions]
L[CDN & Caching]
M[Analytics & Monitoring]
end
A --> D
B --> C
D --> E
E --> F
D --> G
D --> H
D --> I
F --> J
D --> K
A --> L
K --> M
🎯 Architecture Principles
1. Privacy by Design
- Row-level security (RLS) ensures users only access their own data
- JWT-based authentication with automatic token refresh
- No third-party analytics that compromise user privacy
- Local-first data storage with cloud sync
2. Offline-First PWA
- Service Worker handles caching and offline functionality
- Background sync for seamless data synchronization
- IndexedDB for local data persistence
- App Shell architecture for instant loading
3. AI-Powered Personalization
- Context-aware responses considering user history and streaks
- Consistent personality across all AI interactions
- Fallback mechanisms when AI services are unavailable
- Response caching to improve performance and reduce costs
4. Scalable & Maintainable
- TypeScript for type safety and developer experience
- Modular architecture with clear separation of concerns
- API-first design for future mobile app development
- Comprehensive testing at unit, integration, and E2E levels
📱 Frontend Architecture
Component Hierarchy
App Layout
├── Navigation Provider
├── Auth Provider
├── Notification Handler
└── Page Components
├── Meal Tracking Pages
│ ├── MealCard Components
│ ├── MealInput Components
│ └── AI Response Components
├── Dashboard
│ ├── Streak Display
│ ├── Quick Stats
│ └── Recent Activity
└── Profile & Settings
├── User Profile
├── Friend Management
└── Notification Settings
State Management Strategy
// Context-based state management
interface AppState {
user: User | null;
meals: TodaysMeals;
streak: StreakData;
offline: boolean;
}
// Local component state for UI interactions
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
// Server state via SWR for data fetching
const { data: meals, error, mutate } = useSWR('/api/meals/today', fetcher);
Responsive Design System
// Tailwind breakpoint strategy
const breakpoints = {
sm: '640px', // Mobile landscape
md: '768px', // Tablet
lg: '1024px', // Desktop
xl: '1280px', // Large desktop
};
// Component example
<div className="
grid grid-cols-1 gap-4 // Mobile: single column
md:grid-cols-2 md:gap-6 // Tablet: two columns
lg:grid-cols-3 lg:gap-8 // Desktop: three columns
">
🔧 API Architecture
Route Structure
/api/
├── auth/
│ └── callback # OAuth callback handling
├── meals/
│ ├── today # GET: Today's meals
│ ├── log # POST: Log new meal
│ └── check # GET: Check if meal exists
├── ai/
│ ├── chat # POST: Generate meal response
│ └── quote # GET: Daily motivational quote
├── user/
│ ├── profile # GET/PUT: User profile
│ └── friend-code # GET: User's friend code
├── friends/
│ ├── search # GET: Find friends by code
│ └── [operations] # Friend management
├── summaries/
│ ├── [date] # GET: Specific day summary
│ └── recent # GET: Recent summaries
├── admin/
│ ├── stats # GET: System statistics
│ └── [management] # Admin operations
└── cron/
├── lunch # Meal reminders
└── dinner # Meal reminders
Authentication Flow
sequenceDiagram
participant C as Client
participant A as API
participant S as Supabase Auth
C->>A: Request with JWT
A->>A: Extract JWT token
A->>S: Validate token
S->>A: User data or error
A->>A: Check user permissions
A->>C: Response or 401
Error Handling Strategy
// Standardized error response format
interface APIError {
error: string;
code?: string;
details?: any;
}
// Error handling middleware
export function withErrorHandling(handler: APIHandler) {
return async (req: NextRequest) => {
try {
return await handler(req);
} catch (error) {
console.error('API Error:', error);
if (error instanceof ValidationError) {
return NextResponse.json(
{ error: error.message, code: 'VALIDATION_ERROR' },
{ status: 400 }
);
}
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
};
}
💾 Database Architecture
Schema Design Principles
- UUID primary keys for global uniqueness and security
- Foreign key constraints for data integrity
- Indexes on frequently queried columns
- Triggers for automatic data updates
- Row-Level Security (RLS) for user data isolation
Performance Optimizations
-- Composite indexes for common queries
CREATE INDEX idx_meals_user_date_type ON meals(user_id, DATE(logged_at), meal_type);
-- Partial indexes for active data
CREATE INDEX idx_active_users ON users(id) WHERE created_at > NOW() - INTERVAL '30 days';
-- Materialized views for analytics
CREATE MATERIALIZED VIEW daily_stats AS
SELECT
DATE(logged_at) as date,
COUNT(*) as meals_logged,
COUNT(DISTINCT user_id) as active_users
FROM meals
WHERE logged_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY DATE(logged_at);
Data Lifecycle Management
// Automatic data cleanup policies
interface DataRetentionPolicy {
meals: '2 years'; // Keep meal logs for 2 years
summaries: '1 year'; // Keep summaries for 1 year
sessions: '30 days'; // Clean old sessions
logs: '90 days'; // Keep application logs for 90 days
}
// Soft delete pattern for important data
interface SoftDeletable {
deleted_at: Date | null;
deleted_by: string | null;
}
🤖 AI Integration Architecture
GPT-4 Integration Pipeline
graph LR
A[Meal Input] --> B[Context Builder]
B --> C[Prompt Template]
C --> D[GPT-4 API]
D --> E[Response Processor]
E --> F[Cache & Store]
F --> G[Return to User]
subgraph "Context Builder"
H[User Streak]
I[Previous Meals]
J[Time of Day]
K[User Preferences]
end
Prompt Engineering
// Modular prompt system
interface PromptContext {
mealType: MealType;
content: string;
streak: number;
timeOfDay: 'morning' | 'afternoon' | 'evening';
previousMeals: Meal[];
userPreferences?: UserPreferences;
}
// Template system for consistent responses
const PROMPT_TEMPLATES = {
base: `You are a loving, supportive boyfriend who cares deeply about your partner's wellness journey...`,
breakfast: `{base} They just logged breakfast: "{content}". Consider their {streak}-day streak and respond with encouragement...`,
streak_milestone: `{base} They've reached a {streak}-day streak! Celebrate this achievement...`
};
Response Quality Controls
// Response validation and filtering
interface ResponseValidator {
minLength: 50;
maxLength: 200;
requiredTone: 'encouraging' | 'supportive';
bannedWords: string[];
emojiRequired: boolean;
}
// Fallback responses for API failures
const FALLBACK_RESPONSES = {
breakfast: [
"What a great way to start your day! 💕",
"You're taking such good care of yourself! 🌟",
"Perfect fuel for an amazing day ahead! ✨"
]
};
📱 PWA Architecture
Service Worker Strategy
// Multi-layered caching strategy
const CACHE_STRATEGIES = {
'app-shell': 'cache-first', // Static app resources
'api-quotes': 'cache-first', // Daily quotes (rarely change)
'api-meals': 'network-first', // User data (needs freshness)
'api-streaks': 'stale-while-revalidate', // Updated but can show stale
'images': 'cache-first', // Static images
'ai-responses': 'network-only' // Always fresh AI responses
};
Offline Data Synchronization
// Background sync for critical operations
interface SyncOperation {
id: string;
type: 'meal-log' | 'profile-update' | 'friend-add';
data: any;
timestamp: Date;
retries: number;
}
// Conflict resolution strategy
enum ConflictResolution {
CLIENT_WINS = 'client', // User's offline changes take priority
SERVER_WINS = 'server', // Server data is authoritative
MANUAL = 'manual', // Prompt user to resolve
MERGE = 'merge' // Attempt automatic merge
}
Installation & Updates
// Progressive enhancement approach
interface PWAFeatures {
installPrompt: boolean; // Show install banner
backgroundSync: boolean; // Offline data sync
pushNotifications: boolean; // Meal reminders
periodicSync: boolean; // Regular data updates
shareTarget: boolean; // Share meals from other apps
}
🔐 Security Architecture
Authentication & Authorization
// JWT token structure
interface JWTPayload {
sub: string; // User ID
email: string;
iat: number; // Issued at
exp: number; // Expires at
role: 'user' | 'admin';
}
// Permission system
interface Permissions {
'meals:read': boolean;
'meals:write': boolean;
'summaries:read': boolean;
'admin:stats': boolean;
}
Data Protection
-- Row Level Security policies
CREATE POLICY "Users can only see own meals" ON meals
FOR ALL USING (auth.uid() = user_id);
-- Sensitive data encryption
CREATE EXTENSION IF NOT EXISTS pgcrypto;
-- API rate limiting
CREATE TABLE api_rate_limits (
user_id UUID,
endpoint TEXT,
requests INTEGER DEFAULT 1,
window_start TIMESTAMP DEFAULT NOW()
);
📊 Monitoring & Observability
Application Metrics
// Key performance indicators
interface AppMetrics {
// User engagement
dailyActiveUsers: number;
mealLogsPerDay: number;
streakDistribution: number[];
// Technical metrics
apiResponseTimes: number[];
errorRates: Record<string, number>;
uptime: number;
// AI metrics
aiResponseTimes: number[];
aiApiCosts: number;
fallbackResponseRate: number;
}
Error Tracking & Logging
// Structured logging
interface LogEntry {
timestamp: Date;
level: 'info' | 'warn' | 'error';
message: string;
context: {
userId?: string;
endpoint?: string;
error?: Error;
metadata?: any;
};
}
// Performance monitoring
const performanceObserver = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
if (entry.entryType === 'measure') {
trackMetric('performance', entry.name, entry.duration);
}
});
});
🚀 Scalability Considerations
Performance Optimization
// Code splitting strategy
const DashboardPage = lazy(() => import('../pages/Dashboard'));
const MealLogPage = lazy(() => import('../pages/MealLog'));
// Image optimization
const optimizedImages = {
formats: ['webp', 'avif'],
sizes: [640, 768, 1024, 1280],
quality: 80
};
// Database connection pooling
const dbConfig = {
max: 20, // Maximum pool size
idleTimeoutMillis: 30000, // Close idle connections
connectionTimeoutMillis: 2000
};
Horizontal Scaling
# Load balancer configuration
upstream app_servers {
server app1.example.com:3000;
server app2.example.com:3000;
server app3.example.com:3000;
}
# Database read replicas
read_replicas:
- host: read1.example.com
- host: read2.example.com
# CDN strategy
cdn_rules:
- path: "/static/*"
cache_duration: "1y"
- path: "/api/ai/*"
cache_duration: "0"
🔄 Data Flow Examples
Meal Logging Flow
sequenceDiagram
participant U as User
participant C as Client
participant SW as Service Worker
participant API as API Server
participant DB as Database
participant AI as OpenAI
U->>C: Enter meal content
C->>C: Validate input
C->>API: POST /api/meals/log
API->>API: Authenticate user
API->>DB: Insert meal record
API->>AI: Generate response
AI->>API: Return AI response
API->>DB: Update meal with AI response
API->>C: Return complete meal data
C->>SW: Cache response
C->>U: Show success + AI response
Offline Sync Flow
sequenceDiagram
participant U as User
participant C as Client
participant SW as Service Worker
participant IDB as IndexedDB
participant API as API Server
Note over C,IDB: User is offline
U->>C: Log meal
C->>IDB: Store pending sync
C->>U: Show success (pending)
Note over C,API: Connection restored
SW->>IDB: Get pending syncs
SW->>API: Sync meal data
API->>SW: Confirm sync
SW->>IDB: Clear pending sync
SW->>C: Update UI status
📞 Architecture Support
For technical architecture questions or suggestions:
- GitHub Issues: Technical questions
- Architecture Discussions: GitHub Discussions
- Direct Contact:
[email protected]
This architecture supports our mission of creating a supportive, privacy-first meal tracking experience that works reliably across all devices and network conditions. 🏗️💕