A robust Node.js/Express backend API for the Rafeeq educational platform, providing authentication, course management, resource handling, and integration with external services.
- User Authentication: JWT-based authentication with secure password hashing
- Course Management: Create, update, and manage educational courses
- Classroom Operations: Virtual classroom management and student enrollment
- Resource Management: Upload, share, and organize educational resources
- MongoDB Integration: Efficient data storage with Mongoose ODM
- RESTful API: Clean, documented endpoints following REST principles
- Error Handling: Comprehensive error handling and validation
- CORS Support: Configured for cross-origin requests
- Docker Support: Containerized deployment with Docker Compose
- Runtime: Node.js (v18+)
- Framework: Express.js
- Database: MongoDB with Mongoose ODM
- Authentication: JWT (jsonwebtoken) + bcryptjs
- File Upload: Multer
- Validation: Express-validator
- Environment: dotenv
- Containerization: Docker & Docker Compose
- Node.js (v18 or higher)
- MongoDB (v6 or higher) or MongoDB Atlas account
- npm or yarn
- Docker & Docker Compose (optional)
- Clone the repository
git clone https://github.com/Rafeeq-dz/Rafeeq-Backend.git
cd Rafeeq-Backend/server- Install dependencies
npm install- Set up environment variables
Create a .env file in the server directory:
# Server Configuration
PORT=5000
NODE_ENV=development
# Database
MONGODB_URI=mongodb://localhost:27017/rafeeq
# Or use MongoDB Atlas:
# MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/rafeeq?retryWrites=true&w=majority
# JWT Configuration
JWT_SECRET=your_super_secret_jwt_key_here_change_in_production
JWT_EXPIRE=7d
# CORS Configuration
CLIENT_URL=http://localhost:5173
# File Upload Configuration
MAX_FILE_SIZE=52428800
UPLOAD_PATH=./uploads
# AI Service (if using external AI API)
AI_API_URL=https://your-ai-api-url.ngrok-free.dev
AI_API_KEY=your_ai_api_key_here- Start MongoDB (if running locally)
# macOS with Homebrew
brew services start mongodb-community
# Linux with systemd
sudo systemctl start mongod
# Windows
net start MongoDB- Start the development server
npm run devThe API will be available at http://localhost:5000
- Using Docker Compose (Recommended)
cd server
docker-compose up -dThis will start:
- MongoDB container on port 27017
- Node.js API container on port 5000
- Build and run manually
# Build the image
docker build -t rafeeq-backend .
# Run the container
docker run -p 5000:5000 --env-file .env rafeeq-backendserver/
βββ src/
β βββ config/ # Configuration files
β β βββ db.js # MongoDB connection
β βββ controllers/ # Route controllers
β β βββ authController.js
β β βββ courseController.js
β β βββ classroomController.js
β β βββ resourceController.js
β βββ middleware/ # Custom middleware
β β βββ authMiddleware.js # JWT authentication
β β βββ errorHandler.js # Global error handling
β βββ models/ # Mongoose models
β β βββ User.js
β β βββ Course.js
β β βββ Classroom.js
β β βββ Resource.js
β βββ routes/ # API routes
β β βββ authRoutes.js
β β βββ courseRoutes.js
β β βββ classroomRoutes.js
β β βββ resourceRoutes.js
β βββ app.js # Express app setup
β βββ server.js # Server entry point
βββ uploads/ # File upload directory
βββ .env # Environment variables
βββ .gitignore
βββ docker-compose.yml # Docker Compose configuration
βββ Dockerfile # Docker container definition
βββ package.json # Dependencies and scripts
βββ README.md
# Development
npm run dev # Start with nodemon (auto-reload)
npm start # Start production server
# Docker
docker-compose up -d # Start with Docker Compose
docker-compose down # Stop containers
docker-compose logs -f # View logs
# Database
npm run db:seed # Seed database (if script exists)
npm run db:reset # Reset database (if script exists)POST /api/auth/register
Content-Type: application/json
{
"name": "Ahmed Benali",
"email": "ahmed@example.com",
"password": "SecurePass123!",
"specialty": "Computer Science",
"year": 2
}
Response: {
"success": true,
"token": "jwt_token_here",
"user": {
"id": "user_id",
"name": "Ahmed Benali",
"email": "ahmed@example.com"
}
}POST /api/auth/login
Content-Type: application/json
{
"email": "ahmed@example.com",
"password": "SecurePass123!"
}
Response: {
"success": true,
"token": "jwt_token_here",
"user": {...}
}GET /api/auth/me
Authorization: Bearer jwt_token_here
Response: {
"success": true,
"user": {...}
}GET /api/courses
Authorization: Bearer jwt_token_here
Response: {
"success": true,
"count": 10,
"courses": [...]
}GET /api/courses/:id
Authorization: Bearer jwt_token_here
Response: {
"success": true,
"course": {...}
}POST /api/courses
Authorization: Bearer jwt_token_here
Content-Type: application/json
{
"title": "Introduction to Algorithms",
"description": "Learn fundamental algorithms and data structures",
"instructor": "Dr. Karim",
"duration": "12 weeks",
"level": "Intermediate"
}
Response: {
"success": true,
"course": {...}
}POST /api/courses/:id/enroll
Authorization: Bearer jwt_token_here
Response: {
"success": true,
"message": "Enrolled successfully"
}GET /api/classrooms
Authorization: Bearer jwt_token_here
Response: {
"success": true,
"classrooms": [...]
}POST /api/classrooms
Authorization: Bearer jwt_token_here
Content-Type: application/json
{
"name": "CS301 - Data Structures",
"description": "Advanced data structures course",
"capacity": 30
}
Response: {
"success": true,
"classroom": {...}
}POST /api/classrooms/:id/join
Authorization: Bearer jwt_token_here
Response: {
"success": true,
"message": "Joined classroom successfully"
}GET /api/resources
Authorization: Bearer jwt_token_here
Response: {
"success": true,
"resources": [...]
}POST /api/resources
Authorization: Bearer jwt_token_here
Content-Type: multipart/form-data
FormData:
- file: [file]
- title: "Linear Algebra Notes"
- subject: "Mathematics"
- type: "Course Materials"
- description: "Comprehensive notes on linear algebra"
Response: {
"success": true,
"resource": {...}
}POST /api/resources/:id/share
Authorization: Bearer jwt_token_here
Content-Type: application/json
{
"userIds": ["user_id_1", "user_id_2"]
}
Response: {
"success": true,
"message": "Resource shared successfully"
}{
name: String (required),
email: String (required, unique),
password: String (required, hashed),
specialty: String,
year: Number,
role: String (default: 'student'),
enrolledCourses: [CourseId],
classrooms: [ClassroomId],
createdAt: Date,
updatedAt: Date
}{
title: String (required),
description: String,
instructor: String,
duration: String,
level: String,
enrolledStudents: [UserId],
resources: [ResourceId],
createdBy: UserId,
createdAt: Date,
updatedAt: Date
}{
name: String (required),
description: String,
capacity: Number,
students: [UserId],
teacher: UserId,
resources: [ResourceId],
createdAt: Date,
updatedAt: Date
}{
title: String (required),
type: String (required),
subject: String,
description: String,
fileUrl: String,
externalUrl: String,
uploadedBy: UserId,
sharedWith: [UserId],
tags: [String],
downloads: Number,
createdAt: Date,
updatedAt: Date
}The authMiddleware.js protects routes by verifying JWT tokens:
// Usage in routes
router.get('/protected', authMiddleware, controller)How it works:
- Extracts token from
Authorization: Bearer <token>header - Verifies token with JWT_SECRET
- Attaches user object to
req.user - Returns 401 if token is invalid or missing
Global error handler in middleware/errorHandler.js:
{
success: false,
error: "Error message here",
stack: "Stack trace (dev mode only)"
}Error Types:
- 400: Bad Request (validation errors)
- 401: Unauthorized (authentication required)
- 403: Forbidden (insufficient permissions)
- 404: Not Found (resource doesn't exist)
- 500: Internal Server Error
Local MongoDB:
MONGODB_URI=mongodb://localhost:27017/rafeeqMongoDB Atlas:
MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/rafeeqConnection Options (in config/db.js):
{
useNewUrlParser: true,
useUnifiedTopology: true,
serverSelectionTimeoutMS: 5000
}Configure allowed origins in app.js:
cors({
origin: process.env.CLIENT_URL || 'http://localhost:5173',
credentials: true
})Configure in app.js:
multer({
storage: diskStorage({
destination: './uploads/',
filename: (req, file, cb) => {
cb(null, `${Date.now()}-${file.originalname}`)
}
}),
limits: { fileSize: 52428800 }, // 50MB
fileFilter: (req, file, cb) => {
// Validate file types
}
})Production Environment Variables:
NODE_ENV=production
PORT=5000
MONGODB_URI=your_production_mongodb_uri
JWT_SECRET=strong_random_secret_here
CLIENT_URL=https://your-frontend-domain.comHeroku:
heroku login
heroku create rafeeq-backend
git push heroku main
heroku config:set MONGODB_URI=your_mongodb_uri
heroku config:set JWT_SECRET=your_jwt_secretDigitalOcean:
- Create a Droplet (Ubuntu 22.04)
- Install Node.js and MongoDB
- Clone repository
- Set up environment variables
- Use PM2 for process management
npm install -g pm2
pm2 start src/server.js --name rafeeq-backend
pm2 startup
pm2 saveAWS EC2:
- Launch EC2 instance
- Configure security groups (port 5000, 27017)
- Install Node.js and MongoDB
- Deploy with PM2 or Docker
Docker Deployment:
docker-compose -f docker-compose.prod.yml up -d# Run tests (when implemented)
npm test
# Run tests with coverage
npm run test:coverage
# Integration tests
npm run test:integrationProduction Logging:
// Add logging middleware
const morgan = require('morgan');
app.use(morgan('combined'));Error Tracking:
- Integrate Sentry for error tracking
- Set up application monitoring (PM2, New Relic)
- Configure database monitoring
- Fork the repository
- Create your feature branch (
git checkout -b feature/NewEndpoint) - Commit your changes (
git commit -m 'Add new endpoint') - Push to the branch (
git push origin feature/NewEndpoint) - Open a Pull Request
Code Standards:
- Use ES6+ features
- Follow REST conventions
- Add JSDoc comments
- Validate all inputs
- Handle errors properly
- None at the moment
| Variable | Description | Required | Default |
|---|---|---|---|
PORT |
Server port | No | 5000 |
MONGODB_URI |
MongoDB connection string | Yes | - |
JWT_SECRET |
Secret key for JWT | Yes | - |
JWT_EXPIRE |
JWT expiration time | No | 7d |
NODE_ENV |
Environment mode | No | development |
CLIENT_URL |
Frontend URL for CORS | No | http://localhost:5173 |
MAX_FILE_SIZE |
Max upload size in bytes | No | 52428800 |
MongoDB Connection Error:
# Check if MongoDB is running
mongosh
# Or for MongoDB Atlas, verify connection stringPort Already in Use:
# Kill process on port 5000
lsof -ti:5000 | xargs kill -9JWT Errors:
- Verify JWT_SECRET is set
- Check token expiration
- Ensure correct token format:
Bearer <token>
File Upload Errors:
- Check upload directory permissions
- Verify file size limits
- Ensure correct file types
For support, email support@rafeeq.dz or open an issue on GitHub.
This project is proprietary and confidential. Β© 2025 Rafeeq Platform. All rights reserved.
- Express.js - Fast, unopinionated web framework
- MongoDB - Flexible document database
- Mongoose - Elegant MongoDB object modeling
- JWT - Secure authentication standard
- All Contributors - For testing and feedback
Built with β€οΈ for Algerian Students
Last Updated: December 20, 2025