# Architecture Overview & Design Patterns ## System Architecture ### High-Level Architecture ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ Browser │ │ Backend │ │ External │ │ (Frontend) │ │ Services │ │ Services │ │ │ │ │ │ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ React App │◄┼────┼──│ Express API │◄┼────┼──│ GLM-4.6 API │ │ │ │ (Vite) │ │ │ │ (EPUB Gen) │ │ │ │ (Translation)│ │ │ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │ │ │ │ │ │ │ │ ┌─────────────┐ │ │ │ │ ┌─────────────┐ │ │ │ Supabase │◄┼────────────────────┼────┼──│ Supabase │ │ │ │ Auth │ │ │ │ │ Database │ │ │ └─────────────┘ │ │ │ └─────────────┘ │ │ │ │ │ │ │ ┌─────────────┐ │ │ │ │ │ │ Tesseract │ │ │ │ │ │ │ OCR Engine │ │ │ │ │ │ └─────────────┘ │ │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ ``` ### Component Architecture #### Frontend Layer Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ Presentation Layer │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │ │ │ Header │ │ Stepper │ │ Main Content │ │ │ │ Component │ │ Component │ │ (Router Outlet) │ │ │ └─────────────┘ └─────────────┘ └─────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ Application Layer │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │ │ │ Router │ │ State │ │ Utility │ │ │ │ Management │ │ Management │ │ Services │ │ │ │(React Router)│ │ (Zustand) │ │ (API, Auth, Utils) │ │ │ └─────────────┘ └─────────────┘ └─────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ Data Layer │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │ │ │ Browser │ │ Local │ │ External │ │ │ │ Storage │ │ Storage │ │ APIs │ │ │ │ (Blobs, URLs)│ │ (localStorage)│ │ (Supabase, Backend) │ │ │ └─────────────┘ └─────────────┘ └─────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` ## Design Patterns ### 1. State Management Pattern (Zustand) ```javascript // Centralized Store Pattern const useAppStore = create((set, get) => ({ // State uploadedImages: [], cropConfig: {}, ocrText: '', // Actions setUploadedImages: (images) => set({ uploadedImages: images }), resetFromStep: (step) => set((state) => { // Clean, atomic state updates const newState = {}; // Reset logic based on step return newState; }), })); // Usage in components const uploadedImages = useAppStore(state => state.uploadedImages); const setUploadedImages = useAppStore(state => state.setUploadedImages); ``` ### 2. Component Composition Pattern ```javascript // Wizard Step Composition const WizardStep = ({ children, title, onNext, onPrev }) => { return ( {title} {children} ); }; // Specific step implementation const UploadStep = () => { return ( ); }; ``` ### 3. Service Layer Pattern ```javascript // API Service Abstraction export const epubService = { generate: async (text, metadata) => { const response = await fetch(`${API_BASE_URL}/generate-epub`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text, meta: metadata }), }); return response.json(); }, }; // Authentication Service export const authService = { login: async (credentials) => { // Authentication logic }, logout: async () => { // Logout logic }, }; ``` ### 4. Observer Pattern (Authentication) ```javascript // Supabase Auth Observer useEffect(() => { const { data: subscription } = supabaseClient.auth.onAuthStateChange( (event, session) => { if (event === 'SIGNED_IN') { // Handle sign in exchangeGoogleSession(session); } else if (event === 'SIGNED_OUT') { // Handle sign out clearAuthSession(); } } ); return () => subscription.subscription.unsubscribe(); }, []); ``` ### 5. Strategy Pattern (OCR Processing) ```javascript // OCR Language Strategy const ocrLanguageStrategy = { primary: 'tur', fallback: 'eng', detect: async (imageData) => { try { const result = await worker.recognize(imageData, 'tur'); return result.data.text; } catch (error) { // Fallback to English return await worker.recognize(imageData, 'eng'); } }, }; ``` ## Data Flow Architecture ### Unidirectional Data Flow ``` User Action → Component Event → State Update → Re-render → New UI Example: 1. User uploads files 2. Dropzone component triggers onDrop 3. useAppStore.setUploadedImages() called 4. State updated in Zustand store 5. Components subscribed to state re-render 6. New UI shows uploaded images ``` ### Async Data Handling ```javascript // Async Action Pattern const handleOcrProcessing = async () => { try { setTranslationStatus('processing'); setTranslationProgress(0); const processedText = await processOcrImages( croppedImages, (progress) => setTranslationProgress(progress) ); setOcrText(processedText); setTranslationStatus('completed'); } catch (error) { setTranslationError(error.message); setTranslationStatus('error'); } }; ``` ## Component Architecture ### Hierarchy Structure ``` App (Root Component) ├── Header (Authentication & Navigation) ├── Stepper (Wizard Progress) ├── Main Content (Router Outlet) │ ├── UploadStep │ ├── CropStep │ ├── BulkCropStep │ ├── OcrStep │ ├── TranslationStep │ ├── EpubStep │ ├── DownloadStep │ └── Auth Pages └── Error Handling (Snackbar) ``` ### Smart vs Dumb Components ```javascript // Smart Component (Stateful) const OcrStep = () => { const { croppedImages, ocrText, setOcrText } = useAppStore(); const [isProcessing, setIsProcessing] = useState(false); const handleOcrStart = async () => { setIsProcessing(true); // OCR processing logic setOcrText(resultText); setIsProcessing(false); }; return ( ); }; // Dumb Component (Presentational) const OcrProcessing = ({ images, onStart, isProcessing, result }) => { return ( {isProcessing && } {result && } ); }; ``` ## Security Architecture ### Authentication Flow ``` User Login Attempt ↓ Supabase Auth Service ↓ JWT Token Generation ↓ Token Storage (localStorage) ↓ Authenticated API Requests ↓ Token Validation & Refresh ``` ### Data Security Measures ```javascript // Secure API Requests const secureApiCall = async (endpoint, data) => { const token = useAppStore.getState().authToken; return await fetch(endpoint, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify(data), }); }; // Data Sanitization const sanitizeInput = (input) => { return input .trim() .replace(/[<>]/g, '') // Remove potential HTML .substring(0, MAX_LENGTH); // Length limit }; ``` ## Performance Architecture ### Lazy Loading Pattern ```javascript // Code Splitting const UploadStep = lazy(() => import('./components/UploadStep')); const CropStep = lazy(() => import('./components/CropStep')); // Asset Lazy Loading const loadTesseractAssets = async () => { const worker = await createWorker('tur', 1, { workerPath: '/tesseract/worker.min.js', corePath: '/tesseract/tesseract-core-simd-lstm.wasm.js', langPath: '/tesseract/', }); return worker; }; ``` ### Memory Management Pattern ```javascript // Resource Cleanup useEffect(() => { return () => { // Cleanup on unmount if (generatedEpub?.url) { URL.revokeObjectURL(generatedEpub.url); } }; }, []); // Batch Processing Control const processImagesInBatches = async (images, batchSize = 5) => { for (let i = 0; i < images.length; i += batchSize) { const batch = images.slice(i, i + batchSize); await processBatch(batch); // Allow UI to breathe await new Promise(resolve => setTimeout(resolve, 100)); } }; ``` ## Error Handling Architecture ### Error Boundary Pattern ```javascript const ErrorBoundary = ({ children }) => { const [hasError, setHasError] = useState(false); const [error, setError] = useState(null); const handleError = (error, errorInfo) => { setHasError(true); setError(error); // Log error to service logError(error, errorInfo); }; if (hasError) { return ; } return ( {children} ); }; ``` ### Global Error Handling ```javascript // Global Error Store const useErrorStore = create((set) => ({ error: null, setError: (message) => set({ error: message }), clearError: () => set({ error: null }), })); // Error Display Component const ErrorDisplay = () => { const error = useAppStore(state => state.error); const clearError = useAppStore(state => state.clearError); return ( {error} ); }; ``` ## Testing Architecture ### Component Testing Strategy ``` Unit Tests: ├── Utility functions (fileUtils, ocrUtils) ├── Service layer functions └── Custom hooks Integration Tests: ├── Component interactions ├── State management flow └── API service integration E2E Tests: ├── Complete user workflows ├── Authentication flows └── File processing pipelines ``` ## Deployment Architecture ### Build Process ``` Development: ├── Vite dev server ├── Hot module replacement ├── Source maps └── Fast refresh Production: ├── Code optimization ├── Asset bundling ├── Tree shaking └── Compression ``` ### Container Strategy ```dockerfile # Multi-stage Docker build FROM node:18-alpine AS builder # Build stage FROM nginx:alpine AS production # Production stage with static files ``` This architecture provides a robust, scalable foundation for the imgPub application with clear separation of concerns, maintainable code structure, and optimized performance characteristics.