System Overview
This document provides a high-level overview of the LMS architecture, design patterns, and system components.
Architecture Diagram
Architectural Style
The LMS follows a three-tier architecture with clear separation of concerns:
- Presentation Layer - React frontend
- Application Layer - Express backend API
- Data Layer - PostgreSQL database with TypeORM
Additionally, serverless functions on Cloudflare Workers handle specific edge computing tasks.
Core Components
Frontend (Client Application)
Technology: React 19 + TypeScript + Vite
Responsibilities:
- User interface rendering
- Client-side routing
- State management (Redux + TanStack Query)
- Form handling and validation
- Real-time updates
- API communication
Architecture Pattern: Component-based architecture with hooks
Frontend Architecture:
┌─────────────────────────────────────┐
│ React Application │
│ ┌───────────────────────────────┐ │
│ │ Pages & Routing │ │
│ └───────────────────────────────┘ │
│ ┌───────────────────────────────┐ │
│ │ Components (UI) │ │
│ └───────────────────────────────┘ │
│ ┌───────────────────────────────┐ │
│ │ State Management │ │
│ │ (Redux + React Query) │ │
│ └───────────────────────────────┘ │
│ ┌───────────────────────────────┐ │
│ │ API Client (@repo/api) │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────┘Backend (API Server)
Technology: Express 5 + TypeORM + TSOA
Responsibilities:
- RESTful API endpoints
- Business logic execution
- Data validation
- Authentication & authorization
- Database operations
- Integration with external services
- OpenAPI specification generation
Architecture Pattern: Layered architecture (Controller → Service → Repository)
Backend Architecture:
┌─────────────────────────────────────┐
│ Express API Server │
│ ┌───────────────────────────────┐ │
│ │ Controllers (TSOA) │ │
│ │ - Route handlers │ │
│ │ - Request validation │ │
│ └───────────────────────────────┘ │
│ ┌───────────────────────────────┐ │
│ │ Services │ │
│ │ - Business logic │ │
│ │ - Orchestration │ │
│ └───────────────────────────────┘ │
│ ┌───────────────────────────────┐ │
│ │ Integrations │ │
│ │ - External services │ │
│ │ - Gateways │ │
│ └───────────────────────────────┘ │
│ ┌───────────────────────────────┐ │
│ │ TypeORM Entities │ │
│ │ - Data models │ │
│ │ - Relationships │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ PostgreSQL Database │
└─────────────────────────────────────┘Cloud Functions
Technology: Hono + Cloudflare Workers
Responsibilities:
- Edge computing tasks
- File processing
- Lightweight API endpoints
- JWT operations
- Utility functions
Architecture Pattern: Function-as-a-Service (FaaS)
Cloud Functions Architecture:
┌─────────────────────────────────────┐
│ Cloudflare Workers (Edge) │
│ ┌───────────────────────────────┐ │
│ │ Hono Router │ │
│ └───────────────────────────────┘ │
│ ┌───────────────────────────────┐ │
│ │ Functions │ │
│ │ - File operations │ │
│ │ - JWT utilities │ │
│ │ - Data processing │ │
│ └───────────────────────────────┘ │
│ ┌───────────────────────────────┐ │
│ │ Middleware │ │
│ │ - Auth │ │
│ │ - CORS │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────┘Database
Technology: PostgreSQL + TypeORM
Key Entities:
- User, OAuthCredential
- Course, Module, Chapter
- CourseFile, CourseFileMetadata
- Quiz, QuizQuestion, QuizAttempt, QuizResponse
- Assignment (planned)
- Discussion, DiscussionComment
- Conversation, Message
- Calendar, CalendarEvent
- Membership, Role, Permission
- ContentActivity, ChatActivity (analytics)
Relationships: Complex many-to-many and one-to-many relationships with proper foreign keys
Design Patterns
1. Repository Pattern
Location: Backend with TypeORM
TypeORM repositories abstract database operations:
// Entity definition
@Entity()
export class Course {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@OneToMany(() => Module, (module) => module.course)
modules: Module[];
}
// Usage in service
const courseRepo = dataSource.getRepository(Course);
const course = await courseRepo.findOne({
where: { id },
relations: ["modules"],
});2. Dependency Injection
Location: Backend with tsyringe
Controllers and services use dependency injection:
@injectable()
export class CourseService {
constructor(
@inject("DataSource") private dataSource: DataSource,
@inject("StorageService") private storage: IStorageService,
) {}
}3. Factory Pattern
Location: Frontend API queries
Query key factories for consistent cache management:
import { createQueryKeyStore } from "@lukemorales/query-key-factory";
export const queries = createQueryKeyStore({
courses: {
all: null,
detail: (id: string) => [id],
list: (filters) => [{ filters }],
},
});4. Adapter Pattern
Location: Backend integrations
Abstract storage services with adapters:
interface IStorageService {
uploadFile(file: File): Promise<string>;
deleteFile(id: string): Promise<void>;
}
// Firebase adapter
class FirebaseStorageService implements IStorageService {
// Implementation
}
// Appwrite adapter
class AppwriteStorageService implements IStorageService {
// Implementation
}5. Middleware Pattern
Location: Backend Express middleware
Authentication, error handling, and request processing:
// Authentication middleware
export const authenticate = async (req, res, next) => {
const token = req.headers.authorization;
// Verify JWT and attach user to request
next();
};
// Error handling middleware
export const errorHandler = (err, req, res, next) => {
// Centralized error handling
};6. Observer Pattern
Location: Frontend with Redux and TanStack Query
State changes trigger UI updates automatically:
// Component subscribes to state changes
const courses = useSelector((state) => state.courses);
// Query subscriptions
const { data } = useQuery({
queryKey: ["courses"],
queryFn: fetchCourses,
});Data Flow
Request Flow (Frontend → Backend → Database)
User Action
↓
React Component
↓
TanStack Query Hook
↓
API Client (@repo/api)
↓
HTTP Request
↓
Express Server
↓
Controller (TSOA)
↓
Service Layer
↓
TypeORM Repository
↓
PostgreSQL Database
↓
Response (reverse path)Type Flow
Database Entity
↓
TypeORM Entity Decorator
↓
TSOA Controller Annotations
↓
OpenAPI Specification (swagger.json)
↓
openapi-typescript Generator
↓
TypeScript Types (api.gen.ts)
↓
Frontend Components (type-safe!)See Type Safety Flow for detailed information.
Communication Patterns
1. RESTful API
Primary communication between frontend and backend:
GET /api/courses - List courses
GET /api/courses/:id - Get course details
POST /api/courses - Create course
PUT /api/courses/:id - Update course
DELETE /api/courses/:id - Delete course2. Authentication Flow
JWT-based authentication:
1. User logs in with credentials
2. Backend validates and generates JWT
3. Frontend stores JWT (localStorage/Redux)
4. Frontend includes JWT in Authorization header
5. Backend middleware validates JWT on each request
6. User context attached to request3. Real-time Updates (Planned)
For features requiring real-time updates:
- WebSocket connections
- Server-Sent Events (SSE)
- Polling with TanStack Query
Scalability Considerations
Horizontal Scaling
- Frontend: Static assets served via CDN
- Backend: Stateless API servers behind load balancer
- Database: Read replicas for scaling reads
- Cloud Functions: Auto-scaling edge functions
Caching Strategy
Frontend Caching:
- TanStack Query cache for API responses
- Redux persist for application state
- Browser cache for static assets
Backend Caching:
- Database query caching
- Redis for session storage (planned)
- Response caching for expensive operations
Performance Optimization
- Code splitting in frontend (React.lazy)
- Database indexing on frequently queried fields
- Pagination for large data sets
- Lazy loading of related entities
- Asset optimization (images, bundles)
Security Architecture
Authentication
- JWT-based authentication
- OAuth 2.0 for third-party providers (Google, etc.)
- Argon2 password hashing
- JWKS for token verification
Authorization
- Role-based access control (RBAC)
- Permission system for fine-grained control
- Course-level memberships
- Middleware guards on API routes
Data Protection
- HTTPS/TLS for all communications
- SQL injection prevention (TypeORM parameterized queries)
- XSS protection (React auto-escaping)
- CSRF protection
- Input validation and sanitization
Security Headers
- CORS configuration
- Content Security Policy (CSP)
- X-Frame-Options
- X-Content-Type-Options
Monitoring and Observability
Logging
- Structured logging with Pino
- Request/response logging
- Error logging with stack traces
- Audit logs for sensitive operations
Error Handling
- Centralized error handling middleware
- Custom error classes for different scenarios
- User-friendly error messages
- Detailed error logs for debugging
Performance Monitoring
- API response time tracking
- Database query performance
- Frontend render performance
- Resource utilization metrics
Development Principles
Type Safety
- TypeScript strict mode throughout
- No
anytypes without justification - End-to-end type safety
- Compile-time error detection
Code Quality
- ESLint for code linting
- Prettier for formatting
- Comprehensive testing
- Code reviews
- Consistent coding standards
Modularity
- Monorepo structure
- Shared packages
- Clear separation of concerns
- Reusable components and utilities
Developer Experience
- Fast hot reload
- Automated code generation
- Clear error messages
- Comprehensive documentation
- Helpful tooling
Future Enhancements
Potential architectural improvements:
- Microservices: Split backend into domain-specific services
- Message Queue: RabbitMQ/Redis for async processing
- GraphQL: Alternative to REST API
- Real-time: WebSocket server for live updates
- Caching Layer: Redis for distributed caching
- Search Engine: Elasticsearch for full-text search
- Event Sourcing: For audit trails and analytics
Related Documentation
- Type Safety Flow - Detailed type generation process
- Frontend Architecture - Frontend-specific details
- Backend Architecture - Backend-specific details
- Database Package - Database schema and entities