A comprehensive backend system for skill verification, badge management, and professional development tracking with AI-powered features and OAuth integration.
| 🚀 Live Application | 🟢 Up | Visit Frontend App | | 📡 Backend API | 🟢 Up | Base API URL | | 💻 Frontend Repo | 📂 Code | View Frontend Source |
- Overview
- System Architecture
- Features
- Tech Stack
- Project Structure
- Prerequisites
- Installation
- Configuration
- Getting Started
- Running the Application
- Database Seeding
- API Documentation
- Development
- Testing
- Deployment
- Contributing
- License
- Support
The Skill Badge Platform Backend is a robust, scalable Node.js application built with TypeScript that powers a comprehensive skill verification and badge management system. It enables organizations and individuals to create, manage, and verify professional skills through digital badges, with features including AI-powered content generation, real-time discussions, OAuth authentication, and cloud-based media management.
- Multi-provider OAuth Authentication (Google, GitHub)
- AI-Powered Content Generation using OpenRouter integration
- Real-time Discussion Forums for skill-based communities
- Cloud Media Management via Cloudinary
- Email Notifications for user engagement
- Role-Based Access Control (RBAC)
- Badge Verification System with cryptographic proof
- RESTful API with comprehensive endpoints
The platform follows a modular, layered architecture designed for scalability and maintainability:
┌─────────────────────────────────────────────────┐
│ Client Applications (Web/Mobile) │
└───────────────────┬─────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ Express.js REST API Layer │
│ (Routes → Controllers → Services → Models) │
└───────────────────┬─────────────────────────────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌─────────┐
│MongoDB │ │Cloudinary│ │OpenRouter│
│Database│ │ (Media) │ │ (AI) │
└────────┘ └────────┘ └─────────┘
- Separation of Concerns: Clear boundaries between routes, controllers, services, and data models
- Dependency Injection: Loose coupling between components
- Error Handling: Centralized error management with custom error classes
- Security First: JWT authentication, input validation, and sanitization
- Scalability: Stateless design supporting horizontal scaling
- 🔐 JWT-based authentication with refresh tokens
- 🌐 OAuth 2.0 integration (Google, GitHub)
- 👥 Role-based access control (Admin, Instructor, Student)
- 📧 Email verification and password reset
- 🔄 Token refresh mechanism
- 💻 Create and manage coding challenges
- 🔧 Support for multiple programming languages (Python, JavaScript, Java, C++, etc.)
- ⚡ Real-time code execution using Piston API
- 🎯 Challenge categorization by difficulty (EASY, MEDIUM, HARD)
- 🏆 Submission tracking and validation
- 💡 AI-powered hint generation
- 🎮 Random unsolved challenge suggestions
- 📅 Daily randomized challenge selection
- 🎁 Daily challenge motivation system
- ⚙️ Lazy-loading daily challenge creation
- 🔄 One challenge per day rotation
- 🤖 Multi-stream technical interview simulation (Frontend, Backend, Full-stack)
- 🎓 Difficulty levels (Beginner, Intermediate, Advanced)
- 💬 AI-powered conversational interviews with Gemini
- 📊 10-question per interview with final feedback report
- 🎯 Interview status tracking (ACTIVE, COMPLETED)
- ⏱️ Message history and conversation logging
- 📋 Automated scoring system (0-100)
- 🏅 Multi-problem contest management
- ⏱️ Time-limited contest events
- 🎯 Variable point distribution (10, 20, 30, 40 points)
- 👥 Participant tracking and leaderboards
- 📊 Contest-based competitive programming
- 💬 Real-time discussion forums per challenge/badge
- 👥 Comment and reply functionality
- 🔔 Socket.io real-time notifications
- 📝 Post management and moderation
- 👁️ View tracking per post (unique users and guests)
- 📊 View analytics with auto-expiry (24-hour)
- 🏅 Create and manage skill badges
- ✅ Badge verification system
- 📊 Badge analytics and tracking
- 🎨 Custom badge designs with Cloudinary
- 📜 Badge issuance history
- 🎖️ Badge-specific discussion forums
- ☁️ Cloud storage integration (Cloudinary)
- 🖼️ Image upload and optimization
- 📦 File organization and retrieval
- 🔒 Secure media access control
- 👨💼 Comprehensive user management
- 📊 Platform analytics and insights
- 🛠️ Challenge creation and management
- 🎯 Contest management and monitoring
- 📋 Content moderation tools
- 🔧 System configuration and settings
- Runtime: Node.js (≥18.0.0)
- Language: TypeScript (5.0+)
- Framework: Express.js (5.0+)
- Database: MongoDB (v5.0+) with Mongoose ODM
- JWT: JSON Web Tokens for stateless authentication
- Passport.js: OAuth strategies (Google, GitHub)
- bcryptjs: Password hashing and security
- Socket.io: Real-time bidirectional communication for discussions
- HTTP: RESTful API endpoints
- Piston API: Remote code execution for 50+ programming languages
- Google Gemini AI: Conversational AI for technical interviews
- OpenRouter: LLM integration for AI-powered features
- OpenAI: AI content generation
- Cloudinary: Media storage, optimization, and transformation
- SMTP: Email delivery service (Gmail, SendGrid compatible)
- Multer: Multipart form data handling for file uploads
- Streamifier: Stream-based file conversion
- ts-node: TypeScript execution without compilation
- ts-node-dev: Development server with auto-reload
- dotenv: Environment configuration management
- TypeScript: Strict type checking and modern JavaScript features
- Mongoose: MongoDB object modeling
- Axios: HTTP client
- Nodemailer: Email sending
- jsonwebtoken: JWT creation and verification
- cors: Cross-Origin Resource Sharing
- express-validator: Input validation
skill-badge-platform-backend/
├── src/
│ ├── config/ # Configuration files
│ │ ├── cloudinary.ts # Cloudinary setup
│ │ ├── passport.ts # OAuth strategies
│ │ └── seeds/
│ │ └── badgeManifest.ts # Badge seed data
│ │
│ ├── controllers/ # Request handlers
│ │ ├── admin/ # Admin-specific controllers
│ │ │ ├── admin.analytics.controller.ts
│ │ │ ├── admin.Challenge.controller.ts
│ │ │ ├── admin.contest.controller.ts
│ │ │ ├── admin.dashboard.controller.ts
│ │ │ ├── admin.setting.controller.ts
│ │ │ └── admin.user.controller.ts
│ │ ├── auth.controller.ts # Authentication logic
│ │ ├── challenge.controller.ts # Challenge CRUD & logic
│ │ ├── daily.challenge.controller.ts # Daily challenge logic
│ │ ├── discuss.controller.ts # Discussion/posts logic
│ │ ├── interview.controller.ts # Interview system logic
│ │ ├── submission.controller.ts # Code submission & execution
│ │ └── user.controller.ts # User profile management
│ │
│ ├── middleware/ # Custom middleware
│ │ ├── auth.ts # JWT authentication middleware
│ │ ├── role.ts # Role-based access control
│ │ └── upload.ts # Multer file upload handling
│ │
│ ├── models/ # Mongoose schemas
│ │ ├── badge.model.ts # Badge schema
│ │ ├── challenge.model.ts # Challenge schema
│ │ ├── comment.model.ts # Comment schema
│ │ ├── contest.model.ts # Contest schema
│ │ ├── dailyChallenge.model.ts # Daily challenge tracking
│ │ ├── interview.model.ts # Interview session schema
│ │ ├── post.model.ts # Discussion post schema
│ │ ├── submission.model.ts # Code submission schema
│ │ ├── user.model.ts # User schema
│ │ └── view.model.ts # Post view tracking schema
│ │
│ ├── routes/ # API route definitions
│ │ ├── admin.routes.ts # Admin routes
│ │ ├── auth.ts # Authentication routes
│ │ ├── challenge.ts # Challenge routes
│ │ ├── discuss.ts # Discussion routes
│ │ ├── interview.ts # Interview routes
│ │ └── user.ts # User routes
│ │
│ ├── scripts/ # Utility scripts
│ │ ├── seedAdmin.ts # Admin user seeding
│ │ └── seedBadges.ts # Badge seeding
│ │
│ ├── service/ # Business logic layer
│ │ ├── ai.service.ts # AI integration service
│ │ └── badge.service.ts # Badge management service
│ │
│ ├── utils/ # Utility functions
│ │ ├── ai.ts # AI prompt templates
│ │ ├── cloudinary.ts # Cloudinary utilities
│ │ ├── openrouter.ts # OpenRouter API wrapper
│ │ ├── piston.ts # Piston code execution API
│ │ ├── SendMailUtil.ts # Email utility
│ │ └── tokens.ts # JWT token utilities
│ │
│ └── index.ts # Application entry point
│
├── dist/ # Compiled JavaScript (generated)
├── node_modules/ # Dependencies
├── package.json # Project metadata & dependencies
├── tsconfig.json # TypeScript configuration
├── test.js # Test file
└── README.md # This file
Before you begin, ensure you have the following installed:
- Node.js (v18.0.0 or higher)
- npm (v9.0.0 or higher) or yarn
- MongoDB (v5.0 or higher)
- Local installation OR MongoDB Atlas account
- Git for version control
You'll need accounts and API keys for:
- Google OAuth: Google Cloud Console
- GitHub OAuth: GitHub Developer Settings
- Cloudinary: Cloudinary Console
- OpenRouter: OpenRouter Dashboard
- SMTP Service: Gmail, SendGrid, or similar
git clone https://github.com/Sachintha-Prabashana/skillbadge-backend.git
cd skillbadge-backendnpm installCreate a .env file in the root directory:
cp .env.example .envEdit the .env file with your configuration (see Configuration section below).
Create a .env file with the following variables:
# Server Port
PORT=5000
# Node Environment (development | production | test)
NODE_ENV=development# MongoDB Connection URI
MONGO_URI=mongodb://localhost:27017/skill-badge-platform
# For MongoDB Atlas:
# MONGO_URI=mongodb+srv://<username>:<password>@cluster.mongodb.net/<dbname>?retryWrites=true&w=majority# JWT Secret Keys (Generate strong random strings)
JWT_SECRET=your-super-secure-jwt-secret-key-min-32-chars
JWT_REFRESH_SECRET=your-super-secure-refresh-token-secret-key
# Token Expiration
JWT_EXPIRE=7d
JWT_REFRESH_EXPIRE=30d# Google OAuth 2.0 Credentials
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_CALLBACK_URL=http://localhost:5000/api/v1/auth/google/callbackSetup Instructions for Google OAuth:
- Go to Google Cloud Console
- Create a new project or select existing
- Enable Google+ API
- Create OAuth 2.0 credentials
- Add authorized redirect URIs
# GitHub OAuth App Credentials
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
GITHUB_CALLBACK_URL=http://localhost:5000/api/v1/auth/github/callbackSetup Instructions for GitHub OAuth:
- Go to GitHub Developer Settings
- Create a new OAuth App
- Set Authorization callback URL
- Copy Client ID and generate Client Secret
# Cloudinary Cloud Storage
CLOUDINARY_CLOUD_NAME=your-cloudinary-cloud-name
CLOUDINARY_API_KEY=your-cloudinary-api-key
CLOUDINARY_API_SECRET=your-cloudinary-api-secretSetup Instructions for Cloudinary:
- Sign up at Cloudinary
- Navigate to Dashboard
- Copy Cloud name, API Key, and API Secret
# SMTP Server Configuration
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_EMAIL=your-email@gmail.com
SMTP_PASSWORD=your-app-specific-password
# Email From Details
FROM_NAME=Skill Badge Platform
FROM_EMAIL=noreply@skillbadge.comSetup Instructions for Gmail SMTP:
- Enable 2-Factor Authentication on your Google Account
- Generate an App Password: Google App Passwords
- Use the generated password in
SMTP_PASSWORD
# OpenRouter API for AI Features
OPENROUTER_API_KEY=sk-or-v1-your-openrouter-api-keySetup Instructions for OpenRouter:
- Sign up at OpenRouter
- Navigate to API Keys section
- Create a new API key
- Copy the key to your
.envfile
# File Upload Limits
MAX_FILE_SIZE=5242880 # 5MB in bytes
# Rate Limiting
RATE_LIMIT_WINDOW=15 # minutes
RATE_LIMIT_MAX=100 # requests per window
# CORS Origins (comma-separated)
CORS_ORIGIN=http://localhost:3000,http://localhost:3001- Never commit
.envfiles to version control - Use strong, unique secrets for JWT tokens (minimum 32 characters)
- Rotate API keys regularly
- Use environment-specific
.envfiles (.env.development,.env.production) - Store production secrets in secure vaults (AWS Secrets Manager, HashiCorp Vault)
- Clone and install dependencies:
git clone https://github.com/Sachintha-Prabashana/skillbadge-backend.git
cd skillbadge-backend
npm install- Create
.envfile with essential variables:
PORT=5000
NODE_ENV=development
MONGO_URI=mongodb://localhost:27017/skill-badge-platform
JWT_SECRET=your-super-secret-jwt-key-min-32-chars
JWT_REFRESH_SECRET=your-super-secret-refresh-key
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_CALLBACK_URL=http://localhost:5000/api/v1/auth/google/callback
CLOUDINARY_CLOUD_NAME=your-cloud-name
CLOUDINARY_API_KEY=your-api-key
CLOUDINARY_API_SECRET=your-api-secret
OPENROUTER_API_KEY=your-openrouter-api-key
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_EMAIL=your-email@gmail.com
SMTP_PASSWORD=your-app-password- Start the development server:
npm run dev- Create admin user:
npm run seed:admin- Test the API:
curl http://localhost:5000/api/v1/challengesYou need at minimum:
- MongoDB (local or Atlas)
- Node.js 18+
- One OAuth provider (Google or GitHub) OR local JWT testing
- Optional: Cloudinary for media features
For full features:
- Google/GitHub OAuth accounts
- Cloudinary account
- OpenRouter API key (for AI interviews)
- SMTP email service
Run with hot-reload enabled:
npm run devThe server will start on http://localhost:5000 (or your configured PORT).
- Build the TypeScript code:
npm run build- Start the production server:
npm start# Development with auto-reload
npm run dev
# Build TypeScript to JavaScript
npm run build
# Start production server
npm start
# Run tests
npm test
# Lint code
npm run lint
# Format code
npm run format
# Seed admin user
npm run seed:adminTo create an initial admin user for the platform:
npm run seed:adminDefault Admin Credentials:
- Email:
admin@skillbadge.com - Password:
Admin@123
You can modify the src/scripts/seedAdmin.ts file to customize the admin user details.
https://controlled-karina-spsolutions-ea693d09.koyeb.app/api/v1
POST /auth/login
POST /auth/register
POST /auth/logout
POST /auth/refresh-tokenGET /auth/google
GET /auth/google/callback
GET /auth/github
GET /auth/github/callbackGET /challenges
Headers: Authorization: Bearer <token>Response:
{
"challenges": [
{
"_id": "123abc",
"title": "Two Sum",
"difficulty": "EASY",
"description": "Find two numbers that add up to target",
"languages": ["python", "javascript"],
"testCases": [...],
"solved": true
}
],
"totalPages": 5,
"currentPage": 1
}GET /challenges/:id
Headers: Authorization: Bearer <token>POST /challenges/submit
Headers: Authorization: Bearer <token>
Content-Type: application/json
{
"challengeId": "123abc",
"code": "def twoSum(nums, target):\n ...",
"language": "python"
}POST /challenges/run
Headers: Authorization: Bearer <token>
Content-Type: application/json
{
"challengeId": "123abc",
"code": "print('Hello')",
"language": "python"
}Response:
{
"results": [
{
"output": "Hello",
"expected": "Hello",
"passed": true
}
],
"allPassed": true
}POST /challenges/:id/hint
Headers: Authorization: Bearer <token>GET /challenges/random
Headers: Authorization: Bearer <token>GET /challenges/daily/id
Headers: Authorization: Bearer <token>Response:
{
"challengeId": "65a4f8c9d1e2f3g4h5i6j7k8"
}POST /interview/start
Headers: Authorization: Bearer <token>
Content-Type: application/json
{
"stream": "Frontend",
"difficulty": "Intermediate"
}Response:
{
"interviewId": "int_123abc",
"stream": "Frontend",
"difficulty": "Intermediate",
"message": "What is the Virtual DOM and how does it work?"
}POST /interview/chat
Headers: Authorization: Bearer <token>
Content-Type: application/json
{
"interviewId": "int_123abc",
"userAnswer": "The Virtual DOM is a lightweight JavaScript representation of the real DOM..."
}Response:
{
"message": "Great explanation! Now, can you explain React hooks?",
"questionCount": 2,
"isCompleted": false
}Final Response (10th question):
{
"message": "Interview Completed.\n\nFinal Feedback Report:\nScore: 85/100\nStrengths: Good understanding of React fundamentals\nWeaknesses: Need more practice with advanced patterns",
"questionCount": 10,
"isCompleted": true
}GET /discuss
Headers: Authorization: Bearer <token>POST /discuss
Headers: Authorization: Bearer <token>
Content-Type: application/json
{
"title": "Need help with recursion",
"content": "I'm struggling with implementing binary search...",
"challengeId": "123abc",
"tags": ["recursion", "arrays"]
}POST /discuss/:postId/comment
Headers: Authorization: Bearer <token>
Content-Type: application/json
{
"content": "You can use two pointers approach..."
}POST /discuss/:postId/view
Headers: Authorization: Bearer <token>Real-time Socket.io Events:
// Client-side
socket.emit('join_post', postId);
socket.on('new_comment', (comment) => {
// Handle new comment
});GET /users/profile
Headers: Authorization: Bearer <token>PUT /users/profile
Headers: Authorization: Bearer <token>
Content-Type: application/json
{
"firstName": "John",
"lastName": "Doe",
"bio": "Full-stack developer"
}GET /users/stats
Headers: Authorization: Bearer <token>Response:
{
"challengesSolved": 25,
"badges": 5,
"interviewsCompleted": 3,
"totalPoints": 450,
"level": "Gold"
}GET /admin/users # List all users
GET /admin/users/:id # Get user details
PUT /admin/users/:id # Update user
DELETE /admin/users/:id # Delete userPOST /admin/challenges # Create challenge
PUT /admin/challenges/:id # Update challenge
DELETE /admin/challenges/:id # Delete challengePOST /admin/contests # Create contest
GET /admin/contests # List contests
PUT /admin/contests/:id # Update contest
GET /admin/contests/:id/stats # Contest statisticsGET /admin/analytics/dashboard # Platform overview
GET /admin/analytics/users # User statistics
GET /admin/analytics/challenges # Challenge statistics
GET /admin/analytics/contests # Contest statistics- Language: TypeScript with strict type checking
- Style: Follow Express.js and Node.js best practices
- Patterns: MVC architecture with controllers, services, and models
- Error Handling: Centralized error handling middleware
- Validation: Input validation on all endpoints
- Create a feature branch:
git checkout -b feature/your-feature-name-
Make your changes:
- Write clean, documented code
- Follow TypeScript conventions
- Use meaningful variable and function names
-
Test your changes:
npm run dev
# Test endpoints with Postman or curl- Build before commit:
npm run build- Commit with descriptive messages:
git commit -m "feat: add new interview feature"
git push origin feature/your-feature-name# Development with auto-reload
npm run dev
# Build TypeScript
npm run build
# Seed database
npm run seed:admin
# Check for TypeScript errors
npx tsc --noEmitFile uploads are handled through Cloudinary. The upload.ts middleware manages:
- File validation
- Size restrictions
- Format checking
- Security scanning
The platform uses Socket.io for:
- Real-time discussion comments
- Live notification delivery
- Post view count updates
Socket rooms are managed by Post ID for targeted updates.
Use tools like Postman or Insomnia to test API endpoints.
npm testTest complete workflows:
- User registration → Login → Challenge submission
- Interview creation → Answer questions → Get feedback
- Discussion post → Comments → Notifications
The backend can be deployed to:
- Koyeb (Current deployment)
- Heroku
- Railway
- Render
- AWS Elastic Beanstalk
- DigitalOcean App Platform
- Update all environment variables
- Run
npm run buildsuccessfully - Test all OAuth callbacks are correct
- Verify Cloudinary credentials
- Check MongoDB Atlas connection
- Update CORS origins
- Set NODE_ENV=production
- Review security headers
- Test error handling
Development (.env.development):
NODE_ENV=development
DEBUG=trueProduction (.env.production):
NODE_ENV=production
DEBUG=falseWe welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit changes (
git commit -m 'Add AmazingFeature') - Push to branch (
git push origin feature/AmazingFeature) - Open a Pull Request
- Write clear commit messages
- Update documentation for new features
- Test your changes thoroughly
- Follow existing code style
- Add comments for complex logic
This project is licensed under the MIT License - see the LICENSE file for details.
- 📧 Email: sachinthaprabhashana2003@gmail.com
- 🐙 GitHub Issues: Report a bug
- 📚 Documentation: Check README and API docs above
- 💻 Frontend Repo: skillbadge-frontend
MongoDB Connection Error:
- Verify MONGO_URI is correct
- Check MongoDB service is running
- Ensure network access is allowed (Atlas)
OAuth Not Working:
- Verify callback URLs match exactly
- Check client ID and secret are correct
- Clear browser cache and cookies
Email Not Sending:
- Enable "Less secure apps" (Gmail) or use App Password
- Verify SMTP credentials
- Check email quota not exceeded
Code Execution Errors:
- Verify Piston API is accessible
- Check language is supported
- Test with simple code first
- Express.js - Web application framework
- MongoDB - NoSQL database
- Mongoose - MongoDB object modeling
- Socket.io - Real-time communication
- Passport.js - Authentication middleware
- Cloudinary - Cloud media management
- Google Gemini - AI/ML capabilities
- OpenRouter - LLM API aggregation
- Piston - Code execution engine
- TypeScript - Type-safe JavaScript
Special thanks to all contributors who have helped improve this project.
Built with inspiration from modern coding platforms like:
- LeetCode
- HackerRank
- CodeSignal
- InterviewBit
- Express.js community
- MongoDB team
- Node.js developers worldwide
- Open-source contributors
- 📧 Email: sachinthaprabhashana2003@gmail.com
- 🐙 GitHub: @Sachintha-Prabashana
- 🌐 Portfolio: Visit My Site
Features:
- ✅ Authentication (JWT + OAuth)
- ✅ Challenge management with code execution
- ✅ Daily challenge system
- ✅ AI-powered technical interviews
- ✅ Coding contests
- ✅ Real-time discussions
- ✅ Badge system
- ✅ Admin dashboard with analytics
- ✅ Media management (Cloudinary)
- ✅ Socket.io real-time updates
Star this repository if you find it useful! ⭐
© 2025 Skill Badge Platform. All rights reserved.