Backend API untuk aplikasi chat real-time Clavox yang dibangun dengan Node.js + Express + Socket.IO. Menyediakan REST API, real-time messaging, dan sistem autentikasi OTP.
Note: Ini adalah repository backend. Frontend tersedia di Clavox Frontend
- π Phone Authentication dengan OTP verification
- π¬ Real-time Messaging menggunakan Socket.IO
- π JWT Authentication untuk secure API
- π§ OTP Service integration (SMS/WhatsApp)
- πΎ MongoDB Database untuk data persistence
- π‘οΈ Input Validation dengan express-validator
- π Request Logging dengan Morgan
- π CORS Configuration untuk frontend integration
- β‘ Rate Limiting untuk API protection
- π Error Handling middleware
clavox-backend/
βββ src/
β βββ controllers/ # Request handlers
β β βββ authController.js
β β βββ chatController.js
β β βββ userController.js
β βββ middleware/ # Custom middleware
β β βββ auth.js
β β βββ validation.js
β β βββ errorHandler.js
β βββ models/ # Database models
β β βββ User.js
β β βββ Chat.js
β β βββ Message.js
β βββ routes/ # API routes
β β βββ auth.js
β β βββ chat.js
β β βββ users.js
β βββ services/ # Business logic
β β βββ otpService.js
β β βββ smsService.js
β β βββ socketService.js
β βββ utils/ # Helper functions
β β βββ logger.js
β β βββ validators.js
β β βββ helpers.js
β βββ config/ # Configuration files
β β βββ database.js
β β βββ socket.js
β βββ app.js # Express app setup
β βββ server.js # Server entry point
βββ tests/ # Test files
βββ docs/ # API documentation
βββ .env.example # Environment template
βββ package.json
βββ README.md
- Node.js (v16+)
- MongoDB (local atau cloud)
- npm atau yarn
git clone https://github.com/Peter-sour/clavox-backend.git
cd clavox-backend# Core dependencies
npm install
# Production dependencies
npm install express socket.io mongoose cors dotenv
npm install jsonwebtoken bcryptjs
npm install express-validator express-rate-limit
npm install morgan helmet compression
# Development dependencies
npm install --save-dev nodemon concurrently
npm install --save-dev jest supertestCopy .env.example ke .env dan isi konfigurasi:
# Server Configuration
PORT=5000
NODE_ENV=development
# Database
MONGODB_URI=mongodb://localhost:27017/clavox
# atau MongoDB Atlas
# MONGODB_URI=mongodb+srv://<username>:<password>@cluster.mongodb.net/clavox
# JWT Secret
JWT_SECRET=your_super_secret_jwt_key_here
JWT_EXPIRE=7d
# OTP Service (Twilio example)
TWILIO_ACCOUNT_SID=your_twilio_account_sid
TWILIO_AUTH_TOKEN=your_twilio_auth_token
TWILIO_PHONE_NUMBER=your_twilio_phone_number
# CORS Origin
FRONTEND_URL=http://localhost:5173
# Rate Limiting
RATE_LIMIT_WINDOW_MS=900000
RATE_LIMIT_MAX_REQUESTS=100# Pastikan MongoDB running
# Local: mongod
# Atlas: sudah otomatis online
# Jalankan seeder (optional)
npm run seednpm run devServer akan berjalan di http://localhost:5000
POST /api/auth/send-otp
Content-Type: application/json
{
"phoneNumber": "+6281234567890"
}POST /api/auth/verify-otp
Content-Type: application/json
{
"phoneNumber": "+6281234567890",
"otp": "123456"
}POST /api/auth/refresh-token
Authorization: Bearer <refresh_token>GET /api/chats
Authorization: Bearer <access_token>
POST /api/chats
Authorization: Bearer <access_token>
Content-Type: application/json
{
"participants": ["userId1", "userId2"],
"type": "private"
}GET /api/chats/:chatId/messages?page=1&limit=20
Authorization: Bearer <access_token>
POST /api/chats/:chatId/messages
Authorization: Bearer <access_token>
Content-Type: application/json
{
"content": "Hello world!",
"type": "text"
}GET /api/users/profile
Authorization: Bearer <access_token>
PUT /api/users/profile
Authorization: Bearer <access_token>
Content-Type: application/json
{
"name": "John Doe",
"avatar": "avatar_url"
}// Join user to socket
socket.emit('join_user', { userId, token });
// Join chat room
socket.emit('join_chat', { chatId });
// Send message
socket.emit('send_message', {
chatId,
content,
type: 'text'
});
// Typing indicator
socket.emit('typing_start', { chatId });
socket.emit('typing_stop', { chatId });// New message received
socket.on('new_message', (message) => {
console.log('New message:', message);
});
// User typing
socket.on('user_typing', ({ userId, chatId }) => {
console.log(`User ${userId} is typing in ${chatId}`);
});
// User online/offline
socket.on('user_status', ({ userId, status }) => {
console.log(`User ${userId} is ${status}`);
});
// Connection events
socket.on('connect', () => {
console.log('Connected to server');
});
socket.on('disconnect', () => {
console.log('Disconnected from server');
});npm run dev # Development server dengan nodemon
npm run start # Production server
npm run test # Run tests
npm run test:watch # Run tests in watch mode
npm run seed # Database seeding
npm run migrate # Database migration
npm run build # Build untuk production (jika ada transpiling)
npm run lint # ESLint check
npm run lint:fix # Fix ESLint issues{
_id: ObjectId,
phoneNumber: String, // Unique, required
name: String,
avatar: String,
isVerified: Boolean,
lastSeen: Date,
isOnline: Boolean,
createdAt: Date,
updatedAt: Date
}{
_id: ObjectId,
participants: [ObjectId], // User IDs
type: String, // 'private' | 'group'
name: String, // For group chats
avatar: String, // For group chats
lastMessage: ObjectId,
createdAt: Date,
updatedAt: Date
}{
_id: ObjectId,
chatId: ObjectId,
senderId: ObjectId,
content: String,
type: String, // 'text' | 'image' | 'file' | 'voice'
metadata: Object, // File info, image dimensions, etc.
isRead: Boolean,
readBy: [{ userId: ObjectId, readAt: Date }],
createdAt: Date,
updatedAt: Date
}{
_id: ObjectId,
phoneNumber: String,
otp: String,
expiresAt: Date,
isUsed: Boolean,
attempts: Number,
createdAt: Date
}// middleware/auth.js
const jwt = require('jsonwebtoken');
const authenticateToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'Access denied' });
}
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) {
return res.status(403).json({ error: 'Invalid token' });
}
req.user = user;
next();
});
};// services/otpService.js
const generateOTP = () => {
return Math.floor(100000 + Math.random() * 900000).toString();
};
const sendOTP = async (phoneNumber, otp) => {
// Integration dengan Twilio, atau SMS gateway lainnya
// Implementation sesuai provider yang dipilih
};const rateLimit = require('express-rate-limit');
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // limit each IP to 5 requests per windowMs
message: 'Too many authentication attempts'
});const { body, validationResult } = require('express-validator');
const validatePhoneNumber = [
body('phoneNumber')
.isMobilePhone()
.withMessage('Valid phone number required'),
(req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
next();
}
];# Production environment variables
NODE_ENV=production
PORT=5000
MONGODB_URI=mongodb+srv://...
JWT_SECRET=very_secure_secret_keyFROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 5000
CMD ["npm", "start"]version: '3.8'
services:
app:
build: .
ports:
- "5000:5000"
environment:
- NODE_ENV=production
- MONGODB_URI=mongodb://mongo:27017/clavox
depends_on:
- mongo
mongo:
image: mongo:5
ports:
- "27017:27017"
volumes:
- mongo_data:/data/db
volumes:
mongo_data:npm test// tests/auth.test.js
const request = require('supertest');
const app = require('../src/app');
describe('Authentication', () => {
test('POST /api/auth/send-otp', async () => {
const response = await request(app)
.post('/api/auth/send-otp')
.send({ phoneNumber: '+6281234567890' });
expect(response.status).toBe(200);
expect(response.body).toHaveProperty('message');
});
});const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
new winston.transports.File({ filename: 'logs/combined.log' })
]
});- End-to-End Encryption
- File Upload dengan Cloud Storage
- Voice Message Support
- Push Notification Service
- Message Reactions
- User Blocking/Reporting
- Admin Dashboard API
- Analytics & Metrics
- Redis Caching
- Microservices Architecture
-
MongoDB Connection Error
# Check MongoDB status mongod --version # atau untuk service systemctl status mongod
-
Socket.IO CORS Issues
// Pastikan CORS origin sesuai const io = new Server(server, { cors: { origin: process.env.FRONTEND_URL, methods: ["GET", "POST"] } });
-
JWT Token Issues
# Generate new JWT secret node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
# Enable debug logging
DEBUG=express:* npm run dev
# Socket.IO debug
DEBUG=socket.io:* npm run dev- Fork repository ini
- Buat feature branch (
git checkout -b feature/AmazingFeature) - Commit changes (
git commit -m 'Add some AmazingFeature') - Push ke branch (
git push origin feature/AmazingFeature) - Buka Pull Request
Distributed under the MIT License. See LICENSE for more information.
- Express.js - Web Framework
- Socket.IO - Real-time Engine
- MongoDB - Database
- Mongoose - ODM
- JWT - Authentication
Jika project ini membantu, jangan lupa beri β di repo ini!
Link Repository:
- Backend: Clavox Backend
- Frontend: Clavox Frontend
Made with β€οΈ by Peter-sour