Smart healthcare queue management and appointment booking. Built with Node.js, Express, PostgreSQL - fully Dockerized and production-ready.
Four-layer stack with clean separation - HTTP routing, ORM, relational database, all containerized.
Key patterns from the implementation - auth middleware, audit logging, soft-delete hooks.
// JWT authentication + role-based access control const authenticate = async (req, res, next) => { const token = req.headers.authorization?.split(' ')[1]; if (!token) return res.status(401).json({ error: 'Unauthorized' }); const payload = jwt.verify(token, process.env.JWT_SECRET); const user = await User.findByPk(payload.id); if (!user || user.deletedAt) return res.status(401).json({ error: 'User not found' }); req.user = user; next(); }; const authorize = (...roles) => (req, res, next) => { if (!roles.includes(req.user.role)) { return res.status(403).json({ error: 'Insufficient permissions' }); } next(); }; // Usage: router.delete('/staff/:id', authenticate, authorize('admin', 'manager'), handler)
// Automatic audit logging via Sequelize hooks const createAuditLog = async (instance, action, req) => { await AuditLog.create({ userId: req?.user?.id, action, entityType: instance.constructor.name, entityId: instance.id, before: instance._previousDataValues || null, after: instance.dataValues, ipAddress: req?.ip, userAgent: req?.headers['user-agent'], }); }; // Attach to every model that needs auditing [Appointment, Staff, Slot, Service].forEach(Model => { Model.afterCreate(async (inst) => await createAuditLog(inst, 'CREATE')); Model.afterUpdate(async (inst) => await createAuditLog(inst, 'UPDATE')); Model.afterDestroy(async (inst) => await createAuditLog(inst, 'DELETE')); });
// Appointment model with queue management + soft deletes const Appointment = sequelize.define('Appointment', { status: { type: DataTypes.ENUM('scheduled', 'checked_in', 'completed', 'cancelled', 'no_show'), defaultValue: 'scheduled' }, queuePosition: DataTypes.INTEGER, notes: DataTypes.TEXT, checkInTime: DataTypes.DATE, completedTime: DataTypes.DATE, }, { paranoid: true, // soft deletes - sets deletedAt, never destroys rows hooks: { beforeCreate: async (appt) => { // Auto-assign queue position within the day const count = await Appointment.count({ where: { slotId: appt.slotId } }); appt.queuePosition = count + 1; } } });
// Rate limiting - 100 requests per 15 minutes per IP import rateLimit from 'express-rate-limit'; export const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, standardHeaders: true, legacyHeaders: false, handler: (req, res) => res.status(429).json({ error: 'Too many requests', retryAfter: Math.ceil(req.rateLimit.resetTime / 1000), }), }); // Auth endpoints get stricter limits: 5 attempts / 15 min export const authLimiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 5 });
Full REST API covering auth, appointments, slots, staff, branches, services, and audit logs.
Real requests to the live API - running on the production server. No mocks.
Verify the API is online and the database is connected
/healthFetch all clinic branches (Al Khuwair & Salalah seeded)
/api/branchesBrowse available medical services with pricing
/api/servicesView the last 5 audit log entries with user/action tracking
/api/audit-logs?limit=5Production-grade capabilities out of the box - not bolted on after.
Seven models with clear relationships - Branch owns Staff, Slots, and Services. Customers book Appointments.