A comprehensive full-stack online learning platform similar to Coursera, built with Node.js, Express, MongoDB, and vanilla JavaScript. Features include course management, user authentication, role-based access control, enrollment system, and email notifications.
- Features
- Tech Stack
- Project Structure
- Setup Instructions
- API Documentation
- Features Screenshots
- Environment Variables
- Deployment
- Advanced Features
- β User authentication with JWT
- β Role-based access control (User, Premium, Moderator, Admin)
- β Course creation, browsing, and management
- β Course enrollment and tracking system
- β User profiles with course history
- β Course reviews and ratings
- β Email notifications (welcome, enrollment, completion)
- β Responsive UI for mobile and desktop
- β Search and filter courses
- β Course completion certificates
- β RBAC (Role-Based Access Control): 4 user roles with hierarchical permissions
- β SMTP Email Integration: SendGrid/Mailgun/Postmark support with HTML templates
- β Premium content restrictions
- β Form validation on both frontend and backend
- β Global error handling middleware
- β Rate limiting for API security
- β Password hashing with bcrypt
- β Secure HTTP-only cookies
Backend:
- Node.js & Express.js
- MongoDB Atlas (Cloud Database)
- Mongoose ODM
- JWT for authentication
- Bcrypt for password hashing
- Nodemailer for email services
- Express Validator for input validation
Frontend:
- Vanilla JavaScript (ES6+)
- HTML5 & CSS3
- Responsive design (mobile-first)
- Fetch API for HTTP requests
Security & Best Practices:
- Environment variables (.env)
- Rate limiting
- Input validation
- XSS protection
- CORS configuration
- Secure password requirements
online-learning-system/
βββ config/
β βββ db.js # MongoDB connection configuration
βββ controllers/
β βββ authController.js # Authentication logic
β βββ userController.js # User management logic
β βββ courseController.js # Course management logic
βββ middleware/
β βββ auth.js # JWT authentication & RBAC middleware
β βββ validation.js # Input validation rules
β βββ errorHandler.js # Global error handling
βββ models/
β βββ User.js # User schema with roles
β βββ Course.js # Course schema with reviews
βββ routes/
β βββ authRoutes.js # Authentication endpoints
β βββ userRoutes.js # User management endpoints
β βββ courseRoutes.js # Course management endpoints
βββ utils/
β βββ sendEmail.js # Email service utility
βββ public/
β βββ index.html # Frontend application
βββ .env.example # Environment variables template
βββ .gitignore # Git ignore file
βββ package.json # Dependencies
βββ server.js # Express server entry point
βββ README.md # This file
- Node.js (v14 or higher)
- MongoDB Atlas account (free tier available)
- Email service API key (SendGrid/Mailgun/Postmark) - optional for development
-
Clone or download the project files
-
Install dependencies
npm install
-
Set up MongoDB Atlas
- Go to MongoDB Atlas
- Create a free cluster
- Create a database user
- Whitelist your IP address (or use 0.0.0.0/0 for development)
- Get your connection string
-
Configure environment variables
- Copy
.env.exampleto.env
cp .env.example .env
- Edit
.envwith your configuration:
PORT=5000 NODE_ENV=development # MongoDB Atlas Connection String MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/learnhub?retryWrites=true&w=majority # JWT Secret (generate a random string) JWT_SECRET=your_super_secret_jwt_key_change_in_production JWT_EXPIRE=7d # Email Configuration (optional for development) EMAIL_SERVICE=sendgrid EMAIL_API_KEY=your_api_key_here EMAIL_FROM=noreply@learnhub.com EMAIL_FROM_NAME=LearnHub FRONTEND_URL=http://localhost:3000
- Copy
-
Get Email Service API Key (Optional)
- SendGrid: Sign up at sendgrid.com β Get API key
- Mailgun: Sign up at mailgun.com β Get API key
- Postmark: Sign up at postmarkapp.com β Get API key
- For development, the app will use Ethereal Email (test email service)
-
Start the server
# Development mode with auto-restart npm run dev # Production mode npm start
-
Open the application
- Backend API: http://localhost:5000
- Frontend: Open
public/index.htmlin a browser or use a local server
-
Update Frontend API URL (if needed)
- In
public/index.html, change theAPI_URLvariable if your backend runs on a different port:
const API_URL = 'http://localhost:5000/api';
- In
After starting the server, you can:
- Register a new account through the UI
- The first user will have "user" role by default
- To create an admin, you can use MongoDB Compass or Atlas to manually update a user's role to "admin"
http://localhost:5000/api
POST /auth/register
Content-Type: application/json
{
"username": "john_doe",
"email": "john@example.com",
"password": "Password123",
"firstName": "John",
"lastName": "Doe"
}
Response: 201 Created
{
"success": true,
"token": "jwt_token_here",
"user": {
"_id": "user_id",
"username": "john_doe",
"email": "john@example.com",
"role": "user",
...
}
}POST /auth/login
Content-Type: application/json
{
"email": "john@example.com",
"password": "Password123"
}
Response: 200 OK
{
"success": true,
"token": "jwt_token_here",
"user": { ... }
}GET /auth/me
Authorization: Bearer {token}
Response: 200 OK
{
"success": true,
"data": { user_object }
}GET /auth/logout
Authorization: Bearer {token}
Response: 200 OK
{
"success": true,
"message": "Logged out successfully"
}POST /auth/forgot-password
Content-Type: application/json
{
"email": "john@example.com"
}
Response: 200 OK
{
"success": true,
"message": "Password reset email sent"
}GET /users/profile
Authorization: Bearer {token}
Response: 200 OK
{
"success": true,
"data": { user_profile }
}PUT /users/profile
Authorization: Bearer {token}
Content-Type: application/json
{
"username": "new_username",
"email": "new@example.com",
"firstName": "John",
"lastName": "Doe",
"bio": "My bio"
}
Response: 200 OK
{
"success": true,
"data": { updated_user }
}GET /users/my-courses
Authorization: Bearer {token}
Response: 200 OK
{
"success": true,
"count": 5,
"data": [ course_array ]
}GET /users/stats
Authorization: Bearer {token}
Response: 200 OK
{
"success": true,
"data": {
"totalEnrolled": 10,
"totalCompleted": 3,
"inProgress": 7,
"role": "user",
"memberSince": "2024-01-01"
}
}GET /users
Authorization: Bearer {admin_token}
Response: 200 OK
{
"success": true,
"count": 100,
"data": [ users_array ]
}PUT /users/:userId/role
Authorization: Bearer {admin_token}
Content-Type: application/json
{
"role": "premium" // user, premium, moderator, admin
}
Response: 200 OKGET /courses?category=Web Development&level=Beginner&sort=-rating&page=1&limit=10
Query Parameters:
- category: Filter by category
- level: Beginner, Intermediate, Advanced
- minPrice, maxPrice: Price range
- search: Search in title and description
- sort: -createdAt, price, -price, -rating
- page: Page number
- limit: Items per page
Response: 200 OK
{
"success": true,
"count": 10,
"total": 50,
"page": 1,
"pages": 5,
"data": [ courses_array ]
}GET /courses/:courseId
Response: 200 OK
{
"success": true,
"data": {
"_id": "course_id",
"title": "Complete Web Development",
"description": "...",
"instructor": { instructor_details },
"category": "Web Development",
"level": "Beginner",
"duration": 40,
"price": 49.99,
"rating": 4.7,
"reviews": [ reviews_array ],
...
}
}POST /courses
Authorization: Bearer {token}
Content-Type: application/json
{
"title": "Complete Web Development Bootcamp",
"description": "Learn web development from scratch",
"category": "Web Development",
"level": "Beginner",
"duration": 40,
"price": 49.99,
"isPremium": false,
"learningOutcomes": ["HTML", "CSS", "JavaScript"],
"prerequisites": ["Basic computer knowledge"]
}
Response: 201 Created
{
"success": true,
"data": { created_course }
}PUT /courses/:courseId
Authorization: Bearer {token}
Content-Type: application/json
{
"title": "Updated title",
"price": 59.99,
...
}
Response: 200 OKDELETE /courses/:courseId
Authorization: Bearer {token}
Response: 200 OK
{
"success": true,
"message": "Course deleted successfully"
}POST /courses/:courseId/enroll
Authorization: Bearer {token}
Response: 200 OK
{
"success": true,
"message": "Successfully enrolled in course",
"data": { course_details }
}DELETE /courses/:courseId/enroll
Authorization: Bearer {token}
Response: 200 OK
{
"success": true,
"message": "Successfully unenrolled from course"
}POST /courses/:courseId/complete
Authorization: Bearer {token}
Response: 200 OK
{
"success": true,
"message": "Course marked as completed",
"certificateAvailable": true
}POST /courses/:courseId/reviews
Authorization: Bearer {token}
Content-Type: application/json
{
"rating": 5,
"comment": "Excellent course!"
}
Response: 201 Created
{
"success": true,
"message": "Review added successfully"
}PUT /courses/:courseId/publish
Authorization: Bearer {token}
Response: 200 OK
{
"success": true,
"message": "Course published successfully"
}All endpoints return consistent error responses:
{
"success": false,
"message": "Error description",
"errors": [
{
"field": "email",
"message": "Please provide a valid email"
}
]
}Common HTTP Status Codes:
- 200: Success
- 201: Created
- 400: Bad Request (validation errors)
- 401: Unauthorized (not logged in)
- 403: Forbidden (insufficient permissions)
- 404: Not Found
- 500: Internal Server Error
Description: Clean, modern landing page with hero section showcasing the platform's value proposition. Features statistics dashboard showing total courses, instructors, and enrolled students. Displays featured/popular courses in an attractive grid layout with course thumbnails, ratings, and pricing.
Key Elements:
- Gradient hero section with call-to-action button
- Real-time statistics (courses, instructors, students)
- Featured courses carousel
- Responsive grid layout
Description: Comprehensive registration form with real-time validation. Requires username (alphanumeric), valid email, and strong password (6+ characters with uppercase, lowercase, and number). Optional fields for first and last name. Shows inline validation errors and success messages.
Key Features:
- Client-side and server-side validation
- Password strength requirements
- Unique username/email check
- Welcome email sent upon registration
- Smooth modal interface
Description: Simple, secure login interface with email and password fields. Includes "Forgot Password" functionality and link to registration. Returns JWT token stored in localStorage and HTTP-only cookie for security.
Key Features:
- Secure authentication with JWT
- Remember me functionality via localStorage
- Password recovery option
- Error handling for invalid credentials
Description: Comprehensive course browsing interface with advanced filtering and search. Shows all published courses with thumbnails, ratings, instructor names, categories, difficulty levels, and pricing. Supports pagination for large course lists.
Filters Available:
- Text search (title/description)
- Category dropdown
- Difficulty level (Beginner/Intermediate/Advanced)
- Price range
- Sort options (newest, price, rating, popularity)
Description: Detailed course view showing complete information including description, instructor bio, syllabus, learning outcomes, prerequisites, student reviews, and enrollment statistics. Displays enrollment/unenrollment buttons based on user status.
Information Displayed:
- Course thumbnail and title
- Instructor details with bio
- Category, level, duration, price
- Rating and review count
- Detailed description
- Learning outcomes list
- Prerequisites
- Student reviews with ratings
- Enrollment button (or unenroll if enrolled)
Description: Personal dashboard showing all enrolled courses with progress tracking. Displays learning statistics including total enrolled, in-progress, and completed courses. Each course card shows progress status and action buttons.
Features:
- Progress statistics dashboard
- Enrolled courses grid view
- Mark as complete functionality
- Certificate availability indicator
- Unenroll option
- Filter by completion status
Description: Comprehensive user profile management interface showing user information and editable profile form. Displays role badge, member since date, and enrollment statistics. Allows users to update username, email, name, and bio.
Sections:
- User information display (username, email, role, join date)
- Editable profile form
- Role badge with color coding
- Course creation section (for premium+ users)
- Account statistics
Description: Advanced course creation interface available to premium users, moderators, and admins. Multi-field form with validation for creating new courses. Includes all necessary course information fields.
Fields:
- Course title (max 200 chars)
- Description (max 2000 chars)
- Category dropdown (12 categories)
- Difficulty level
- Duration in hours
- Price (USD)
- Premium course checkbox
- Learning outcomes (optional)
- Prerequisites (optional)
Description: Demonstration of the 4-tier role system with different permissions and capabilities for each role type. Visual indicators (badges) show user roles throughout the interface.
Role Hierarchy:
- User (Blue badge): Can browse and enroll in free courses, view profile
- Premium (Yellow badge): All user features + create courses, access premium content
- Moderator (Purple badge): All premium features + manage users, publish/unpublish any course
- Admin (Red badge): Full system access, manage all users and courses, change user roles
Description: Automated email system sending HTML-formatted emails for various events. Uses SendGrid/Mailgun/Postmark APIs with fallback to Ethereal Email for development.
Email Types:
- Welcome Email: Sent upon registration with platform introduction
- Enrollment Confirmation: Sent when enrolling in a course
- Course Completion: Sent with congratulations and certificate info
- Password Reset: Sent with secure reset token link (1-hour expiration)
Email Features:
- HTML templates with styling
- Platform branding
- Secure token-based password reset
- Environment-based configuration
- Error handling (app continues if email fails)
Description: Fully responsive interface that adapts seamlessly to mobile devices, tablets, and desktops. Uses mobile-first CSS approach with breakpoints for optimal viewing on all screen sizes.
Mobile Optimizations:
- Collapsible navigation menu
- Stacked form layouts
- Touch-friendly buttons (minimum 44px)
- Optimized font sizes
- Single-column course grid on small screens
- Modal dialogs fit mobile viewports
Description: Interactive review system allowing enrolled students to rate courses (1-5 stars) and leave comments. Displays average rating and review count. Reviews include username, star rating, and comment text.
Features:
- 5-star rating system
- Text comments (max 500 chars)
- Average rating calculation
- Review count display
- One review per user per course
- Chronological review display
Create a .env file in the root directory with the following variables:
# Server Configuration
PORT=5000
NODE_ENV=development
# MongoDB Atlas Connection (REQUIRED)
MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/learnhub?retryWrites=true&w=majority
# JWT Configuration (REQUIRED)
JWT_SECRET=generate_a_random_secure_string_here
JWT_EXPIRE=7d
# Email Service Configuration (OPTIONAL - uses Ethereal in development if not set)
EMAIL_SERVICE=sendgrid # Options: sendgrid, mailgun, postmark
EMAIL_API_KEY=your_api_key_here
EMAIL_FROM=noreply@yourplatform.com
EMAIL_FROM_NAME=Learning Platform
# Frontend URL (for CORS and email links)
FRONTEND_URL=http://localhost:3000
# Rate Limiting
RATE_LIMIT_WINDOW_MS=900000 # 15 minutes
RATE_LIMIT_MAX_REQUESTS=100MONGODB_URI: Your MongoDB Atlas connection stringJWT_SECRET: Random secure string for JWT signing
- Email configuration (uses test email service in development if not provided)
- Rate limiting (uses defaults if not provided)
-
Create account on Render.com
-
Create new Web Service
- Connect your GitHub repository
- Or upload your code
-
Configure Build Settings
- Build Command:
npm install - Start Command:
npm start
- Build Command:
-
Add Environment Variables
- Add all required variables from
.env - Set
NODE_ENV=production
- Add all required variables from
-
Deploy
- Render will automatically deploy your app
- Get your deployment URL
-
Create account on Railway.app
-
New Project from GitHub
- Connect repository
- Railway auto-detects Node.js
-
Add Environment Variables
- Go to Variables tab
- Add all required variables
-
Deploy
- Railway automatically deploys
- Get your deployment URL
-
Import from GitHub
- Create new Repl
- Import from GitHub repository
-
Configure Secrets
- Use Secrets tab (padlock icon)
- Add environment variables
-
Run
- Click Run button
- Replit provides a URL
-
Update Frontend API URL
- In
public/index.html, updateAPI_URLto your backend URL - Example:
const API_URL = 'https://your-app.onrender.com/api';
- In
-
Update CORS Settings
- In
server.js, update CORS origin to your frontend URL
- In
-
Test All Features
- Registration and login
- Course creation and enrollment
- Email notifications
- Profile updates
-
Create Admin User
- Register a user
- Use MongoDB Atlas to manually set role to "admin"
The system implements a hierarchical 4-tier role system:
// Role Hierarchy (higher number = more permissions)
{
'user': 1, // Basic access
'premium': 2, // Can create courses
'moderator': 3, // Can manage content
'admin': 4 // Full access
}Permissions Matrix:
| Feature | User | Premium | Moderator | Admin |
|---|---|---|---|---|
| Browse Courses | β | β | β | β |
| Enroll in Free Courses | β | β | β | β |
| Enroll in Premium Courses | β | β | β | β |
| Create Courses | β | β | β | β |
| Edit Own Courses | β | β | β | β |
| Edit Any Course | β | β | β | β |
| Delete Own Courses | β | β | β | β |
| Delete Any Course | β | β | β | β |
| View All Users | β | β | β | β |
| Change User Roles | β | β | β | β |
| Publish/Unpublish Courses | β | Own | Any | Any |
Supports multiple SMTP providers:
SendGrid Setup:
EMAIL_SERVICE=sendgrid
EMAIL_API_KEY=SG.xxxxxxxxxxxxx
EMAIL_FROM=noreply@yourdomain.comMailgun Setup:
EMAIL_SERVICE=mailgun
EMAIL_API_KEY=your-mailgun-api-key
EMAIL_USERNAME=postmaster@yourdomain.com
EMAIL_FROM=noreply@yourdomain.comPostmark Setup:
EMAIL_SERVICE=postmark
EMAIL_API_KEY=your-postmark-server-token
EMAIL_FROM=noreply@yourdomain.comEmail Templates Included:
- Welcome email (HTML formatted)
- Enrollment confirmation
- Course completion with certificate notification
- Password reset with secure token
Development Mode:
- Automatically uses Ethereal Email (fake SMTP)
- Logs preview URLs to console
- No actual emails sent
-
Password Security
- Bcrypt hashing with salt rounds
- Minimum 6 characters
- Requires uppercase, lowercase, and number
- Never stored in plain text
-
JWT Authentication
- Secure token generation
- 7-day expiration
- Stored in HTTP-only cookies
- Also available in localStorage for frontend
-
Input Validation
- Express Validator on all inputs
- Client-side validation
- XSS protection
- SQL injection prevention (NoSQL)
-
Rate Limiting
- 100 requests per 15 minutes per IP
- Prevents brute force attacks
- Configurable limits
-
CORS Configuration
- Whitelist specific origins
- Credentials support
- Secure headers
Authentication:
- β Register new user with valid data
- β Register with invalid data (check validation)
- β Login with correct credentials
- β Login with incorrect credentials
- β Access protected routes without token
- β Logout functionality
User Management:
- β View profile
- β Update profile information
- β Update with invalid data
- β View enrolled courses
- β View user statistics
Course Management:
- β Browse all courses
- β Filter by category
- β Filter by level
- β Search courses
- β View course details
- β Create course (as premium user)
- β Create course (as regular user - should fail)
- β Update own course
- β Delete own course
- β Enroll in course
- β Unenroll from course
- β Mark course as complete
- β Add course review
- β Publish/unpublish course
Role-Based Access:
- β Regular user accessing premium content
- β Premium user creating courses
- β Moderator managing content
- β Admin changing user roles
- β Admin viewing all users
Email Notifications:
- β Welcome email on registration
- β Enrollment confirmation email
- β Course completion email
- β Password reset email
Users Collection:
{
username: String,
email: String,
password: String (hashed),
role: String (user/premium/moderator/admin),
firstName: String,
lastName: String,
bio: String,
enrolledCourses: [ObjectId],
completedCourses: [ObjectId],
createdAt: Date
}Courses Collection:
{
title: String,
description: String,
instructor: ObjectId (ref: User),
instructorName: String,
category: String,
level: String (Beginner/Intermediate/Advanced),
duration: Number,
price: Number,
isPremium: Boolean,
enrolledStudents: [ObjectId],
rating: Number,
reviews: [{
user: ObjectId,
username: String,
rating: Number,
comment: String,
createdAt: Date
}],
isPublished: Boolean,
createdAt: Date
}All API responses follow this consistent format:
Success Response:
{
"success": true,
"data": { ... },
"message": "Optional success message"
}Error Response:
{
"success": false,
"message": "Error description",
"errors": [ ... ] // Optional validation errors
}This is an educational project. Feel free to fork and modify for your learning purposes.
MIT License - Feel free to use this project for learning and development.
For issues or questions:
- Check the API documentation above
- Review the error messages in the console
- Ensure all environment variables are set correctly
- Verify MongoDB Atlas connection string is correct
- Check that the frontend API_URL matches your backend URL
- Express.js Documentation
- MongoDB Documentation
- Mongoose Documentation
- JWT Introduction
- Node.js Best Practices
Built with β€οΈ for learning and education
Last Updated: February 2026