Universal Queue Management System - A completely generic, white-label Queue Management System that works for any business: Banks, Hospitals, Government Offices, Salons, Restaurants, Universities, DMVs, Clinics, etc.
This is a monorepo containing both the backend (NestJS) and frontend (Next.js) applications.
- Framework: Node.js 20 + NestJS 10
- Database: Microsoft SQL Server (via TypeORM)
- Real-Time: Socket.io
- Authentication: JWT + Refresh Tokens
- SMS: Twilio
- Email: Resend
- Documentation: Swagger/OpenAPI
- Framework: Next.js 14
- Styling: Tailwind CSS
- State Management: Zustand
- Real-Time: Socket.io Client
- UI Components: Custom components with Framer Motion
- One separate queue per Agent/Counter (not one big queue)
- Customers choose Service Category → automatically routed to least busy Agent in that category
- Agents can only see and control their own queue
- Admin has full visibility and override capability
- Real-time everywhere (Dashboards, Display Screens, Customer Status)
- Ticket printing + SMS + Email virtual tickets
- Public REST API for 3rd-party systems
- Analytics & Reports available only to Admin
- Zero trust – Agents cannot modify other queues
For a quick setup, follow these essential steps:
- Install Prerequisites: Node.js 20.x and Microsoft SQL Server
- Install Dependencies:
npm install(root) andnpm install(frontend) - Configure Environment: Create
.envwith database and JWT settings (see Environment Variables) - Setup Database: Run
npm run setup:dbto create database and admin user - Start Backend:
npm run start:dev(runs on port 3000) - Start Frontend:
cd frontend && npm run dev(runs on port 3001) - Login: Use
masteradmin/admin(change password immediately!)
For detailed instructions, see the Installation section below.
Before starting, ensure you have the following installed:
- Node.js 20.x (LTS recommended)
- Microsoft SQL Server (2017 or later) - SQL Server Express is sufficient for development
- npm (comes with Node.js)
# Install backend dependencies
npm install
# Install frontend dependencies
cd frontend
npm install
cd ..Create a .env file in the root directory with the following variables:
# Database Configuration (MS SQL Server)
DB_HOST=localhost
DB_PORT=1433
DB_USERNAME=sa
DB_PASSWORD=YourSQLServerPassword
DB_DATABASE=qms_db
DB_ENCRYPT=true
DB_TRUST_CERT=true
# JWT Authentication
JWT_SECRET=your-super-secret-jwt-key-change-in-production-min-32-chars
JWT_EXPIRES_IN=15m
JWT_REFRESH_SECRET=your-super-secret-refresh-key-change-in-production-min-32-chars
JWT_REFRESH_EXPIRES_IN=7d
# Encryption Key (for sensitive data encryption)
# Generate a secure 64-character hex key for production
ENCRYPTION_KEY=your-generated-64-character-hex-key-or-leave-empty-for-dev-default
# Application
PORT=3000
NODE_ENV=development
# Optional: Redis (for Socket.io scaling in production)
# REDIS_HOST=localhost
# REDIS_PORT=6379
# Optional: Twilio SMS Configuration
# TWILIO_ACCOUNT_SID=your-twilio-account-sid
# TWILIO_AUTH_TOKEN=your-twilio-auth-token
# TWILIO_PHONE_NUMBER=+1234567890
# Optional: Resend Email Configuration
# RESEND_API_KEY=your-resend-api-key
# RESEND_FROM_EMAIL=noreply@yourdomain.comImportant Notes:
- Replace
YourSQLServerPasswordwith your actual SQL Server password - For production, generate strong secrets for
JWT_SECRETandJWT_REFRESH_SECRET(minimum 32 characters) - Generate a secure
ENCRYPTION_KEYfor production (64-character hex string) - For local development with SQL Server Express, you may need to set
DB_TRUST_CERT=trueandDB_ENCRYPT=false
Create a frontend/.env.local file:
NEXT_PUBLIC_API_URL=http://localhost:3000
NEXT_PUBLIC_SOCKET_URL=http://localhost:3000- Ensure SQL Server is running - Start SQL Server service on your machine
- Verify SQL Server Authentication - Ensure SQL Server is configured for Mixed Mode authentication (SQL Server and Windows Authentication)
- Check SQL Server Port - Default port is 1433. Verify it's open and accessible
The setup script will:
- Create the database if it doesn't exist
- Create all required tables (Users, Categories, AgentCategories, Tickets)
- Create a default admin user
# Run the database setup script
npm run setup:dbWhat the script does:
- Connects to SQL Server using credentials from
.env - Creates the
qms_dbdatabase if it doesn't exist - Initializes encryption service
- Creates all database tables using TypeORM
- Creates default admin user with credentials:
- Username/Email:
masteradmin - Password:
admin
- Username/Email:
Connection Refused Error:
- Ensure SQL Server service is running
- Check that port 1433 is correct (or your custom port)
- Verify host, username, and password in
.envfile - Ensure SQL Server allows TCP/IP connections (check SQL Server Configuration Manager)
Authentication Failed:
- Verify username and password are correct
- Ensure SQL Server authentication is enabled (Mixed Mode)
- Check that the user has CREATE DATABASE privileges
- For SQL Server Express, ensure you're using the
saaccount or a user with sufficient privileges
Database Already Exists:
- The script will not fail if the database exists
- It will update tables if schema has changed
- It will update the admin user if it exists
Port Warning:
- If you see a warning about port 3306 or 5432, you may have incorrect database settings
- MS SQL Server default port is 1433
- Update your
.envfile with correct MS SQL Server settings
If you prefer to set up the database manually:
-
Create the database:
CREATE DATABASE qms_db;
-
Update
.envwith your database credentials -
Run the application - Tables will be created automatically if
synchronize: trueis enabled (development only) -
Create admin user - Use the script or manually insert:
npm run setup:db
# Development
npm run start:dev
# Production
npm run build
npm run start:prodThe API will be available at http://localhost:3000
Swagger documentation at http://localhost:3000/api
# Navigate to frontend directory
cd frontend
# Development
npm run dev
# Production
npm run build
npm startThe frontend will be available at http://localhost:3001 (or next available port)
POST /queue/check-in- Customer check-in, create ticketGET /queue/status- Get public status pageGET /queue/ticket/:tokenNumber- Get ticket by token numberGET /categories/public- Get active categories
POST /auth/login- Login (Agent/Admin)POST /auth/refresh- Refresh access token
GET /queue/agent/my-queue- Get my queuePOST /queue/agent/call-next- Call next ticketPATCH /queue/agent/:ticketId/serving- Mark as servingPATCH /queue/agent/:ticketId/complete- Mark as completedPATCH /queue/agent/:ticketId/no-show- Mark as no-showPUT /queue/agent/reorder- Reorder my queuePOST /queue/agent/:ticketId/transfer/:newAgentId- Transfer ticket
POST /users- Create userGET /users- Get all usersGET /users/agents- Get all agentsGET /users/:id- Get user by IDPUT /users/:id- Update userDELETE /users/:id- Delete user
POST /categories- Create categoryGET /categories- Get all categoriesGET /categories/:id- Get category by IDPUT /categories/:id- Update categoryDELETE /categories/:id- Delete categoryPOST /categories/:categoryId/assign-agent/:agentId- Assign agent to categoryDELETE /categories/:categoryId/remove-agent/:agentId- Remove agent from category
GET /queue/admin/all- Get all queuesGET /queue/admin/ticket/:id- Get ticket by IDPATCH /queue/admin/:ticketId/override- Admin override any ticket
GET /analytics/dashboard- Get dashboard statisticsGET /analytics/avg-wait-time- Average wait timeGET /analytics/avg-service-time- Average service timeGET /analytics/peak-hours- Peak hours heatmapGET /analytics/abandonment-rate- Abandonment rateGET /analytics/agent-performance- Agent performance rankingGET /analytics/category-stats- Category statisticsGET /analytics/export/excel- Export to Excel
Connect to ws://localhost:3000/queue namespace:
join-agent-room- Join agent's room (requires agentId)join-category-room- Join category room (requires categoryId)join-public-room- Join public status room
ticket:created- New ticket createdticket:called- Ticket calledticket:serving- Ticket being servedticket:completed- Ticket completedticket:no-show- Ticket marked as no-showticket:transferred- Ticket transferredqueue:updated- Queue updatedstatus:updated- Public status updated
- Customer Flow: Check-in, category selection, token generation, status page
- Agent Dashboard: Queue management, call next, mark as serving/completed
- Admin Panel: Users, categories, queues, analytics management
- Real-time Updates: Socket.io integration for live updates
- Responsive Design: Tailwind CSS for modern UI
frontend/
app/
customer/ # Customer flow pages
check-in/ # Check-in form
token/[token] # Token display page
agent/ # Agent pages
login/ # Agent login
dashboard/ # Agent dashboard
admin/ # Admin pages
login/ # Admin login
dashboard/ # Admin dashboard
users/ # Users management
categories/ # Categories management
queues/ # All queues view
analytics/ # Analytics dashboard
status/ # Public status page
lib/
api.ts # API client
auth.ts # Authentication utilities
socket.ts # Socket.io client
- Customer/Public: Can check-in and view status (no login required)
- Agent: Can manage own queue, call next, mark as serving/completed/no-show, reorder queue, transfer tickets
- Admin: Full access to all features, user management, categories, analytics, override capabilities
When a customer checks in and selects a category, the system automatically:
- Finds all active agents assigned to that category
- Calculates which agent has the fewest pending tickets
- Routes the ticket to that agent
- Generates a unique token number
- Sends SMS/Email notifications (if configured)
- Each agent has their own separate queue
- Agents can reorder their queue
- Agents can transfer tickets to other agents (if they handle the same category)
- Real-time updates via WebSocket
- Average wait time
- Average service time
- Peak hours heatmap
- Abandonment rate
- Agent performance ranking
- Category statistics
- Excel export
| Variable | Description | Default | Example |
|---|---|---|---|
DB_HOST |
SQL Server host address | localhost |
localhost or 192.168.1.100 |
DB_PORT |
SQL Server port | 1433 |
1433 |
DB_USERNAME |
SQL Server username | sa |
sa or your SQL user |
DB_PASSWORD |
SQL Server password | (empty) | Your SQL password |
DB_DATABASE |
Database name | qms_db |
qms_db |
DB_ENCRYPT |
Enable encryption for connection | true |
true or false |
DB_TRUST_CERT |
Trust server certificate | true |
true (for self-signed certs) |
JWT_SECRET |
Secret key for JWT tokens | (required) | Min 32 characters |
JWT_EXPIRES_IN |
Access token expiration | 15m |
15m, 1h, 7d |
JWT_REFRESH_SECRET |
Secret key for refresh tokens | (required) | Min 32 characters |
JWT_REFRESH_EXPIRES_IN |
Refresh token expiration | 7d |
7d, 30d |
ENCRYPTION_KEY |
Key for data encryption | (optional) | 64-character hex string |
PORT |
Backend server port | 3000 |
3000 |
NODE_ENV |
Environment mode | development |
development or production |
| Variable | Description | Default |
|---|---|---|
REDIS_HOST |
Redis host (for Socket.io scaling) | localhost |
REDIS_PORT |
Redis port | 6379 |
TWILIO_ACCOUNT_SID |
Twilio account SID | (none) |
TWILIO_AUTH_TOKEN |
Twilio auth token | (none) |
TWILIO_PHONE_NUMBER |
Twilio phone number | (none) |
RESEND_API_KEY |
Resend API key | (none) |
RESEND_FROM_EMAIL |
Default from email address | (none) |
Create frontend/.env.local:
| Variable | Description | Example |
|---|---|---|
NEXT_PUBLIC_API_URL |
Backend API URL | http://localhost:3000 |
NEXT_PUBLIC_SOCKET_URL |
WebSocket server URL | http://localhost:3000 |
JWT Secrets:
# Generate a secure JWT secret (32+ characters)
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"Encryption Key:
# Generate a secure encryption key (64-character hex)
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"Create a .env file in the root directory:
# ============================================
# Database Configuration (MS SQL Server)
# ============================================
DB_HOST=localhost
DB_PORT=1433
DB_USERNAME=sa
DB_PASSWORD=YourSQLServerPassword
DB_DATABASE=qms_db
DB_ENCRYPT=true
DB_TRUST_CERT=true
# ============================================
# JWT Authentication
# ============================================
JWT_SECRET=your-super-secret-jwt-key-change-in-production-min-32-chars
JWT_EXPIRES_IN=15m
JWT_REFRESH_SECRET=your-super-secret-refresh-key-change-in-production-min-32-chars
JWT_REFRESH_EXPIRES_IN=7d
# ============================================
# Encryption (for sensitive data)
# ============================================
ENCRYPTION_KEY=your-generated-64-character-hex-key-or-leave-empty-for-dev-default
# ============================================
# Application Settings
# ============================================
PORT=3000
NODE_ENV=development
# ============================================
# Optional: Redis (for Socket.io scaling)
# ============================================
# REDIS_HOST=localhost
# REDIS_PORT=6379
# ============================================
# Optional: Twilio SMS
# ============================================
# TWILIO_ACCOUNT_SID=your-twilio-account-sid
# TWILIO_AUTH_TOKEN=your-twilio-auth-token
# TWILIO_PHONE_NUMBER=+1234567890
# ============================================
# Optional: Resend Email
# ============================================
# RESEND_API_KEY=your-resend-api-key
# RESEND_FROM_EMAIL=noreply@yourdomain.com# Run in development mode with hot reload
npm run start:dev
# Run tests
npm run test
# Lint code
npm run lint
# Format code
npm run formatcd frontend
# Run development server
npm run dev
# Lint code
npm run lintFollow these steps in order:
- Install Node.js 20.x
- Install and configure Microsoft SQL Server
- Clone the repository
- Run
npm installin root directory - Run
npm installinfrontenddirectory - Create
.envfile with database and JWT configuration - Create
frontend/.env.localwith API URLs - Ensure SQL Server is running
- Run
npm run setup:dbto create database and tables - Verify admin user was created (username:
masteradmin, password:admin) - Start backend:
npm run start:dev - Start frontend:
cd frontend && npm run dev - Access application at
http://localhost:3001 - Change default admin password after first login
-
Environment Configuration:
- Set
NODE_ENV=productionin.env - Set
synchronize: falsein database config (already set) - Generate and set strong JWT secrets (minimum 32 characters)
- Generate and set secure
ENCRYPTION_KEY(64-character hex) - Configure production database credentials
- Set
-
Database:
- Run
npm run setup:dbon production server - Or use migrations for schema management
- Ensure database backups are configured
- Run
-
Security:
- Use strong passwords for database
- Enable SSL/TLS for database connections
- Set
DB_ENCRYPT=trueand configure certificates - Review and restrict CORS origins
- Use environment-specific secrets
-
Scaling:
- Configure Redis for Socket.io scaling (if needed)
- Set up load balancing if required
- Use process manager (PM2, systemd, etc.)
-
Build and Deploy:
npm run build npm run start:prod
-
Environment Variables:
- Set production API URLs in
frontend/.env.local:NEXT_PUBLIC_API_URL=https://api.yourdomain.com NEXT_PUBLIC_SOCKET_URL=https://api.yourdomain.com
- Set production API URLs in
-
Build:
cd frontend npm run build npm start -
Deployment Options:
- Vercel: Supports Next.js natively, automatic deployments
- Docker: Containerize the application
- Traditional Hosting: Build and serve static files or use Node.js server
- All environment variables configured
- Strong JWT secrets generated
- Encryption key generated and secured
- Database backups configured
- SSL/TLS certificates installed
- CORS origins restricted
- Error logging and monitoring set up
- Process manager configured (PM2/systemd)
- Firewall rules configured
- Regular security updates scheduled
MIT