Back to projects

CourseSpace

CourseSpace is a modern, premium SaaS Course Selling platform built using the MERN stack. Designed with a dark-mode first aesthetic, it provides seamless content delivery for students and a complete CRUD management system for course creators.

ReactExpressMongoDBNode.js
Zod schema validation
Cloudinary CDN uploads
IP rate limiters & security
Winston & Morgan logs
CourseSpace preview

Overview

The e-learning industry is crowded with platforms that either charge high transaction fees or suffer from poor visual execution and fragile security. CourseSpace was engineered to solve these bottlenecks.

It is a self-hosted, scalable, and secure SaaS application that combines a smooth, glassmorphic UI with hardened security protocols, automatic media optimization, and robust system observability.

The Problem Statement

Typical DIY course-selling websites face several core engineering and product challenges:

  • Security Vulnerabilities: Open endpoints leave courses vulnerable to unauthorized downloads, brute-force admin logins, and NoSQL injections.
  • Media Management Complexity: Storing high-resolution course thumbnails and lesson videos locally slows down request speeds and balloons hosting costs.
  • Cluttered UI/UX: Traditional dashboards are often visually dry and non-responsive, degrading the learning experience.
  • Zero Production Observability: When server errors or bad requests occur in production, developers are left in the dark without physical logs.

The Solution

CourseSpace addresses these issues directly by decoupling client-side presentation from core business logic, resulting in:

  • A hardened backend protected by security headers (helmet), IP rate limiters, and zod schema validations.
  • Offloaded media processing via integration with the Cloudinary CDN.
  • A beautifully animated, theme-aware React frontend using vanilla CSS variables for glassmorphism and responsiveness.
  • Production logging through physical rolling file logs using winston and morgan.

System Architecture & Schema Design

The architecture separates core application concern layers while using strict validation schemas and middleware guards to isolate administrative actions:

The relational relationships inside MongoDB are strictly maintained using ObjectIds and model references:

[Student / Admin Client] ──> [Frontend Client (React/Vite)]
                                    │ (HTTPS Requests)
                                    ▼
                     [Rate Limiter & Helmet Headers]
                                    │ (Validated Payload)
                                    ▼
                          [Express API Router]
                       ┌────────────┴────────────┐
                       ▼                         ▼
            [Admin Auth Middleware]    [User Auth Middleware]
             (Multer Buffer stream)              │
                       ├─────────────────────────┤
                       ▼                         ▼
               [Cloudinary CDN]           [MongoDB Atlas]
                                                 ▲
                                                 │
          [Winston Logger] <── [Morgan Stream] ──┘
  • Users / Admins: Distinct collections keeping authentication credentials separated. Passwords are encrypted using bcrypt (salt rounds: 5).
  • Courses: Tracks titles, descriptions, pricing, and creator IDs.
  • Lessons: Linked to Courses with a 1-to-many relationship (ref: 'courses'), storing descriptions, video URLs, and order priorities.
  • Purchases: Join-table collection mapping courseId to userId to authorize video stream access.

Key Engineering Highlights & Code Patterns

Engineering focus was centered around payload integrity, secure storage pipelines, and robust debugging paths:

  • A. Strict Payload Validation & Schema Protection (Zod): To prevent malicious database inputs and NoSQL injections, all incoming payloads are run through strict schemas before processing: const zodadminschema = z.object({ email: z.string().email(), password: z.string().min(6).regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])/), firstName: z.string().min(3).max(20), lastName: z.string().min(3).max(20) });
  • B. Cloud Media Pipeline (Cloudinary + Multer): Course creators can upload custom course thumbnails. The backend intercepts the file buffer via multer and streams it directly to Cloudinary to keep the application stateless: adminRouter.post("/course", adminMiddleware, upload.single("image"), async function (req, res, next) { const adminId = req.userId; const { title, description, price } = createCourseSchema.parse(req.body); const course = await courseModel.create({ title, description, price, imageUrl: req.file.path, creatorId: adminId }); });
  • C. Hardened API Security Middlewares: The server uses helmet to manage HTTP security headers and prevents DDoS/brute-force attacks with IP rate limiting: const rateLimit = require("express-rate-limit"); const limiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 100, standardHeaders: true, legacyHeaders: false });
  • D. Observability & Logging: All incoming HTTP requests and internal execution errors are logged directly to filesystem streams using winston and morgan: app.use(morgan('combined', { stream: { write: message => logger.info(message.trim()) } }));

Challenges Faced & Key Resolutions

Developing and optimizing CourseSpace presented several complex integration challenges:

  • Challenge 1: Video Security & Embedded Content Control • Issue: Direct exposure of video files results in pirated content. • Resolution: Implemented a robust YouTube Player API overlay in React. Raw video identifiers are rendered through an custom player container, blocking context-menus and using sandboxed iframe attributes to prevent students from inspecting source links or leaving the viewport.
  • Challenge 2: Decoupled Styling Without Layout Shifts (CLS) • Issue: Using massive UI component libraries caused cumulative layout shifts on slow networks and custom theme mismatches. • Resolution: Wrote structured Vanilla CSS from scratch using HSL design tokens. Set custom variables inside :root (for light theme) and [data-theme="dark"] to toggle global themes instantly with CSS transitions.

Results & Key Takeaways

The final delivery met all validation metrics and established clean deployment practices:

  • Observability: Added logging reduced troubleshooting time in production down to seconds by having searchable physical logs.
  • Stateless Scaling: Moving course thumbnail processing to Cloudinary allowed the backend instances to scale horizontally without syncing local directories.
  • Security Confidence: Zero payload validation bypasses during stress testing due to Zod's strict schema verification before database operations.
  • Responsive Design: 100% mobile responsiveness achieved using CSS grid and flexbox, ensuring smooth usage on tablets, mobile devices, and desktops.