A production-ready school management system built with NestJS, using event-driven microservices architecture with Apache Kafka for inter-service communication and Prisma for database management.
┌─────────────────┐
│ API Gateway │ ← HTTP/REST (Port 3000)
│ (Gateway) │
└────────┬────────┘
│ Kafka RPC
├─────────────┬─────────────┬─────────────┬─────────────┬─────────────┐
▼ ▼ ▼ ▼ ▼ ▼
┌────────┐ ┌─────────┐ ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌───────┐
│ Auth │ │ Student │ │ Teacher │ │Academics │ │ Activity │ │ Email │
└────────┘ └─────────┘ └─────────┘ └──────────┘ └──────────┘ └───────┘
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
[DB] [DB] [DB] [DB] [DB] [SMTP]
| Service | Description | Port | Database |
|---|---|---|---|
| Gateway | API Gateway, routing, authentication, public endpoints | 3000 | PostgreSQL (Public) |
| Auth | User authentication, JWT tokens, password management | - | PostgreSQL |
| Student | Student profile, enrollment, records | - | PostgreSQL |
| Teacher | Teacher profile, assignments | - | PostgreSQL |
| Academics | School, classes, subjects, curriculum | - | PostgreSQL |
| Activity | School activities, events, attendance | - | PostgreSQL |
| Email notifications (SMTP) | - | - |
- Node.js 20+
- Docker & Docker Compose
- Git (optional, for cloning)
That's it! Everything else (Kafka, PostgreSQL, databases) is handled by Docker Compose.
Option A: Clone with Git (Recommended)
git clone https://github.com/masabinhok/sms-api.git
cd sms-apiOption B: Download ZIP
- Go to https://github.com/masabinhok/sms-api
- Click the green "Code" button → "Download ZIP"
- Extract and navigate to the folder
For Windows (PowerShell as Admin):
# Enable script execution (first time only)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
# Run setup
.\scripts\setup.ps1For Linux/Mac:
chmod +x scripts/setup.sh
./scripts/setup.shThis script will:
- ✅ Install all npm dependencies
- ✅ Create
.envfile from template - ✅ Start Kafka cluster (3 brokers) + PostgreSQL
- ✅ Create all databases automatically
- ✅ Generate Prisma clients
- ✅ Run all database migrations
- ✅ Seed sample data (users, academics, teachers, students)
Then start the services:
npm run devFor detailed step-by-step instructions, see SETUP.md - A complete beginner-friendly guide!
npm installdocker-compose up -dThis starts:
- 3 Kafka brokers (ports 9094, 9095, 9096)
- Kafka UI (http://localhost:8080)
- PostgreSQL with all databases (port 5432)
Security Warning: Never commit
.envfiles to version control. Use the provided.env.exampleas a template.
# Copy the example file
cp .env.example .env
# The default values work with docker-compose!
# No changes needed for local development
⚠️ Email Service Configuration Required: To enable email notifications (password resets, contact inquiries, etc.), you must configure your own SMTP credentials in the.envfile:
SMTP_HOST,SMTP_PORT,SMTP_USER,SMTP_PASS- For Gmail: Enable 2FA and generate an App Password
- Without email configuration, the email service will start but emails won't be sent
# Generate Prisma clients
npx prisma generate --schema=apps/auth/prisma/schema.prisma
npx prisma generate --schema=apps/student/prisma/schema.prisma
npx prisma generate --schema=apps/teacher/prisma/schema.prisma
npx prisma generate --schema=apps/academics/prisma/schema.prisma
npx prisma generate --schema=apps/activity/prisma/schema.prisma
npx prisma generate --schema=apps/gateway/prisma/schema.prisma
# Run migrations
npx prisma migrate deploy --schema=apps/auth/prisma/schema.prisma
npx prisma migrate deploy --schema=apps/student/prisma/schema.prisma
npx prisma migrate deploy --schema=apps/teacher/prisma/schema.prisma
npx prisma migrate deploy --schema=apps/academics/prisma/schema.prisma
npx prisma migrate deploy --schema=apps/activity/prisma/schema.prisma
npx prisma migrate deploy --schema=apps/gateway/prisma/schema.prisma# Seed all databases at once
npm run seed:all
# Or seed individually
npm run seed:auth # Create sample users (admin, teachers, students, guardians)
npm run seed:academics # Create school info, classes, subjects
npm run seed:teacher # Create sample teacher profiles
npm run seed:student # Create sample student profilesDefault credentials after seeding:
- Admin:
admin@school.edu/Password123! - Teacher:
john.smith@school.edu/Password123! - Student:
emma.thompson@student.school.edu/Password123!
# Development mode (all services in parallel)
npm run dev
# Or start individually
npm run start:gateway
npm run start:auth
npm run start:student
npm run start:teacher
npm run start:academics
npm run start:activity
npm run start:email- API Gateway: http://localhost:3000
- Swagger UI: http://localhost:3000/api/v1/api/docs
- Health Check: http://localhost:3000/api/v1/health
- Kafka UI: http://localhost:8080
- PostgreSQL: localhost:5432 (user: postgres, pass: postgres)
npm run start:auth # Auth service
npm run start:student # Student service
npm run start:teacher # Teacher service
npm run start:academics # Academics service
npm run start:activity # Activity service
npm run start:email # Email service
npm run start:gateway # API Gatewaynpx prisma generate --schema=apps/<service>/prisma/schema.prismanpm run test # Unit tests
npm run test:watch # Watch mode
npm run test:cov # Coverage
npm run test:e2e # E2E testsnpm run seed:all # Seed all services
npm run seed:auth # Seed users only
npm run seed:academics # Seed academics only
npm run seed:teacher # Seed teachers only
npm run seed:student # Seed students only- Centralized error handling with custom exception filters
- Prisma error mapping to HTTP status codes
- Structured error responses with timestamps and context
- See EXCEPTION_HANDLING.md
/health- Full system health (memory, disk, Kafka)/health/ready- Readiness probe for Kubernetes/health/live- Liveness probe- See HEALTH_CHECKS.md
- NestJS Logger for services
- Context-aware logging with service names
- Production-ready log formatting
- See LOGGING.md
- Bcrypt hashing (12 rounds)
- Password validation rules
- Secure token management
- See PASSWORD_SECURITY.md
- Prisma interactive transactions
- Rollback on failure
- See TRANSACTION_MANAGEMENT.md
Problem: Services fail to connect to Kafka brokers
Error: Failed to connect to kafka brokerSolution:
- Verify Kafka containers are running:
docker-compose ps - Check Kafka broker ports are accessible:
localhost:9094,9095,9096 - Restart Kafka cluster:
docker-compose restart - Check Kafka UI at http://localhost:8080 to verify cluster health
Problem: Prisma migration fails
Error: P1001: Can't reach database serverSolution:
- Verify PostgreSQL is running and accessible
- Check database URL in
.envfile - Ensure database exists:
CREATE DATABASE academics; - Test connection:
npx prisma db pull --schema=apps/academics/prisma/schema.prisma
Problem: Gateway fails to start on port 3000
Error: listen EADDRINUSE: address already in use :::3000Solution:
- Find process using port:
Get-Process -Id (Get-NetTCPConnection -LocalPort 3000).OwningProcess - Kill the process or change
PORTin.env
Problem: Module not found errors for Prisma client
Error: Cannot find module '@prisma/client'Solution:
# Regenerate Prisma clients for all services
npx prisma generate --schema=apps/auth/prisma/schema.prisma
npx prisma generate --schema=apps/student/prisma/schema.prisma
npx prisma generate --schema=apps/teacher/prisma/schema.prisma
npx prisma generate --schema=apps/academics/prisma/schema.prisma
npx prisma generate --schema=apps/activity/prisma/schema.prismaProblem: Microservice doesn't respond to requests Solution:
- Check service logs for errors
- Verify Kafka consumer group is active (check Kafka UI)
- Ensure service is registered with correct topic name
- Restart the specific service
# Submit contact inquiry
curl -X POST http://localhost:3000/api/v1/public/contact-inquiry \
-H "Content-Type: application/json" \
-d '{
"name": "John Doe",
"email": "john@example.com",
"phone": "+1-555-0123",
"subject": "Admission Information",
"message": "I would like to know more about the admission process."
}'
# Schedule campus visit
curl -X POST http://localhost:3000/api/v1/public/schedule-visit \
-H "Content-Type: application/json" \
-d '{
"name": "Jane Smith",
"email": "jane@example.com",
"phone": "+1-555-0456",
"preferredDate": "2025-12-15",
"preferredTime": "10:00 AM",
"numberOfVisitors": "2",
"notes": "Interested in science facilities"
}'
# Request brochure
curl -X POST http://localhost:3000/api/v1/public/brochure-request \
-H "Content-Type: application/json" \
-d '{
"name": "Mike Johnson",
"email": "mike@example.com",
"phone": "+1-555-0789"
}'# Register a new user
curl -X POST http://localhost:3000/api/v1/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "admin@school.com",
"password": "SecurePass123!",
"role": "ADMIN"
}'
# Login
curl -X POST http://localhost:3000/api/v1/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "admin@school.com",
"password": "SecurePass123!"
}'
# Response includes access_token and refresh_token# Full health check
curl http://localhost:3000/api/v1/health
# Readiness probe
curl http://localhost:3000/api/v1/health/ready
# Liveness probe
curl http://localhost:3000/api/v1/health/liveFor interactive API testing, visit:
- Swagger Documentation: http://localhost:3000/api/v1/api/docs
- All endpoints with request/response schemas
- Built-in "Try it out" functionality
- Never commit
.envfiles to version control - Use
.env.exampleas a template - Rotate JWT secrets regularly in production
- Use strong, unique passwords for databases
- Enable HTTPS/TLS for all services
- Use managed secrets (AWS Secrets Manager, Azure Key Vault, etc.)
- Implement rate limiting on API Gateway
- Enable Kafka authentication and encryption
- Use read-only database replicas for read operations
- Implement audit logging for sensitive operations
- Use least-privilege database users per service
- Enable SSL for database connections
- Regular backups with encryption
- Implement row-level security where applicable
- Fork the repository and clone locally
- Create a feature branch:
git checkout -b feature/your-feature-name - Install dependencies:
npm install - Make your changes and test thoroughly
- Run linting:
npm run lint - Run tests:
npm run test - Commit with conventional commits:
feat: add new featurefix: resolve bugdocs: update documentationrefactor: restructure code
- Push and create a Pull Request
- Follow existing code style (ESLint + Prettier configured)
- Write unit tests for new features
- Update documentation for API changes
- Keep commits atomic and well-described
- Provide clear description of changes
- Reference related issues:
Closes #123 - Ensure CI checks pass
- Request review from maintainers
The project uses GitHub Actions for automated testing and validation:
- Linting: ESLint checks on every commit
- Testing: Jest unit and e2e tests
- Build: TypeScript compilation validation
- Prisma: Schema validation and migration checks
- Development: Auto-deploy to dev environment on
mainbranch - Staging: Manual approval required
- Production: Tagged releases only (
v*.*.*)
- Render: Current hosting platform (see
render.yaml) - Kubernetes: Production-ready manifests in
k8s-deployment.yaml - Docker: Multi-stage Dockerfile for optimized builds
- Health Endpoints:
/health,/health/ready,/health/live - Kubernetes Probes: Configured in deployment manifests
- Uptime Monitoring: Configure external monitoring (e.g., UptimeRobot)
- Structured Logging: NestJS Logger with context
- Log Levels: Configurable via environment variables
- Production Logs: Centralized logging recommended (ELK, CloudWatch, etc.)
- See LOGGING.md for implementation details
Recommended implementations:
- Prometheus: Metrics collection
- Grafana: Metrics visualization
- Jaeger/Zipkin: Distributed tracing for microservices
- Kafka Monitoring: Use Kafka UI (http://localhost:8080) in development
- Implement error tracking service (Sentry, Rollbar, etc.)
- All exceptions are structured and logged
- See EXCEPTION_HANDLING.md
docker build -t sms-gateway:latest .docker run -p 3000:3000 \
-e KAFKA_BROKERS="kafka1:9092,kafka2:9092,kafka3:9092" \
-e JWT_ACCESS_SECRET="secret" \
sms-gateway:latestkubectl apply -f k8s-deployment.yamlIncludes:
- Deployment with 3 replicas
- Health checks (liveness & readiness probes)
- LoadBalancer service
- Environment configuration
- Architecture - System design and data flow
- Exception Handling - Error management patterns
- Health Checks - Monitoring and readiness probes
- Logging - Structured logging implementation
- Password Security - Authentication best practices
- Transaction Management - Database consistency
- Framework: NestJS 11
- Language: TypeScript 5.7
- Message Broker: Apache Kafka (KRaft mode)
- Database: PostgreSQL (via Prisma 6)
- API Documentation: Swagger/OpenAPI
- Validation: class-validator, class-transformer
- Authentication: JWT, bcrypt
- Testing: Jest
- Containerization: Docker, Kubernetes
npm run dev # Start all services in development
npm run build # Build production bundle
npm run start:prod # Start production server
npm run lint # Lint code
npm run format # Format code with Prettier
npm run seed:all # Seed all databases (auth, academics, teachers, students)
npm run seed:auth # Seed auth database (users)
npm run seed:academics # Seed academics database (school, classes, subjects)
npm run seed:teacher # Seed teacher database
npm run seed:student # Seed student database| Variable | Description | Default |
|---|---|---|
PORT |
Gateway HTTP port | 3000 |
JWT_ACCESS_SECRET |
Access token secret | - |
JWT_REFRESH_SECRET |
Refresh token secret | - |
JWT_ACCESS_EXPIRE |
Access token expiry | 15m |
JWT_REFRESH_EXPIRE |
Refresh token expiry | 7d |
KAFKA_BROKERS |
Kafka broker addresses | localhost:9094,... |
*_DATABASE_URL |
Service database URLs | - |
DATABASE_URL_PUBLIC |
Public data database URL | - |
ADMIN_EMAIL |
Admin notification email | admin@school.edu |
FRONTEND_URL |
Frontend application URL | http://localhost:4000 |
This project is licensed under the MIT License - see the LICENSE file for details.
Sabin Shrestha (@masabinhok)
- 📧 Email: sabin.shrestha.er@gmail.com
- 🌐 Website: sabinshrestha69.com.np
- 💻 GitHub: @masabinhok
For support, email sabin.shrestha.er@gmail.com or open an issue in the GitHub repository.
⭐ Star this repository if you find it helpful!
Made with ❤️ by Sabin Shrestha