Building a School Management System (SMS) helps educational institutions digitize their operations—streamlining how administrators, teachers, students, and parents interact with school data. In this guide, you'll learn how to build a complete School Management System using the MERN stack (MongoDB, Express.js, React, Node.js).
We’ll cover:
- User authentication
- Student and teacher management
- Class scheduling
- Attendance tracking
- A basic React-based dashboard
Table of Contents
- Project Setup
- Authentication System
- Student Management
- Teacher Management
- Class Scheduling
- Attendance Tracking
- React Frontend Setup
- Conclusion
- Author & Resources
1. Project Setup
Backend Setup
mkdir backend && cd backend
npm init -y
npm install express mongoose dotenv bcryptjs jsonwebtoken cors
Frontend Setup
npx create-react-app frontend
cd frontend
npm install axios react-router-dom
2. Authentication System (Node.js)
/models/User.js
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const userSchema = new mongoose.Schema({
name: String,
email: { type: String, unique: true },
password: String,
role: { type: String, enum: ['admin', 'teacher', 'student'], default: 'student' },
});
userSchema.pre('save', async function () {
if (!this.isModified('password')) return;
this.password = await bcrypt.hash(this.password, 12);
});
module.exports = mongoose.model('User', userSchema);
/routes/userRoutes.js
const express = require('express');
const router = express.Router();
const User = require('../models/User');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
router.post('/register', async (req, res) => {
const { name, email, password, role } = req.body;
const user = new User({ name, email, password, role });
await user.save();
res.status(201).json({ message: 'User registered' });
});
router.post('/login', async (req, res) => {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user || !(await bcrypt.compare(password, user.password)))
return res.status(401).json({ error: 'Invalid credentials' });
const token = jwt.sign({ id: user._id, role: user.role }, process.env.JWT_SECRET);
res.json({ token });
});
module.exports = router;
3. Student Management
/models/Student.js
const mongoose = require('mongoose');
const studentSchema = new mongoose.Schema({
name: String,
age: Number,
grade: String,
parentContact: String,
});
module.exports = mongoose.model('Student', studentSchema);
/routes/studentRoutes.js
const express = require('express');
const router = express.Router();
const Student = require('../models/Student');
router.get('/', async (req, res) => {
const students = await Student.find();
res.json(students);
});
router.post('/', async (req, res) => {
const student = new Student(req.body);
await student.save();
res.status(201).json(student);
});
module.exports = router;
4. Teacher Management
/models/Teacher.js
const mongoose = require('mongoose');
const teacherSchema = new mongoose.Schema({
name: String,
subject: String,
email: String,
phone: String,
});
module.exports = mongoose.model('Teacher', teacherSchema);
/routes/teacherRoutes.js
const express = require('express');
const router = express.Router();
const Teacher = require('../models/Teacher');
router.get('/', async (req, res) => {
const teachers = await Teacher.find();
res.json(teachers);
});
router.post('/', async (req, res) => {
const teacher = new Teacher(req.body);
await teacher.save();
res.status(201).json(teacher);
});
module.exports = router;
5. Class Scheduling
/models/Class.js
const mongoose = require('mongoose');
const classSchema = new mongoose.Schema({
className: String,
teacher: { type: mongoose.Schema.Types.ObjectId, ref: 'Teacher' },
students: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Student' }],
scheduleTime: String,
});
module.exports = mongoose.model('Class', classSchema);
/routes/classRoutes.js
const express = require('express');
const router = express.Router();
const Class = require('../models/Class');
router.get('/', async (req, res) => {
const classes = await Class.find().populate('teacher students');
res.json(classes);
});
router.post('/', async (req, res) => {
const newClass = new Class(req.body);
await newClass.save();
res.status(201).json(newClass);
});
module.exports = router;
6. Attendance Tracking
/models/Attendance.js
const mongoose = require('mongoose');
const attendanceSchema = new mongoose.Schema({
student: { type: mongoose.Schema.Types.ObjectId, ref: 'Student' },
date: { type: Date, default: Date.now },
status: { type: String, enum: ['present', 'absent'], default: 'present' },
});
module.exports = mongoose.model('Attendance', attendanceSchema);
/routes/attendanceRoutes.js
const express = require('express');
const router = express.Router();
const Attendance = require('../models/Attendance');
router.post('/', async (req, res) => {
const attendance = new Attendance(req.body);
await attendance.save();
res.status(201).json(attendance);
});
router.get('/:studentId', async (req, res) => {
const records = await Attendance.find({ student: req.params.studentId });
res.json(records);
});
module.exports = router;
7. Frontend Integration (React)
/frontend/src/pages/Dashboard.js
import React, { useEffect, useState } from 'react';
import axios from 'axios';
const Dashboard = () => {
const [students, setStudents] = useState([]);
const [teachers, setTeachers] = useState([]);
useEffect(() => {
axios.get('http://localhost:5000/api/students').then(res => setStudents(res.data));
axios.get('http://localhost:5000/api/teachers').then(res => setTeachers(res.data));
}, []);
return (
<div>
<h1>Dashboard</h1>
<section>
<h2>Students</h2>
<ul>
{students.map(s => (
<li key={s._id}>{s.name} - Grade {s.grade}</li>
))}
</ul>
</section>
<section>
<h2>Teachers</h2>
<ul>
{teachers.map(t => (
<li key={t._id}>{t.name} - {t.subject}</li>
))}
</ul>
</section>
</div>
);
};
export default Dashboard;
8. Conclusion
This School Management System provides:
- Role-based user access
- Student and teacher CRUD operations
- Class scheduling with relationships
- Attendance tracking per student
- A clean React frontend to tie it together
You can deploy this stack using Render (backend) and Netlify/Vercel (frontend), with MongoDB Atlas as your database.
For a production-grade version, consider:
- Role-based access middleware
- Form validation
- PDF generation for reports
- Calendar UI for schedules
9. Author & Resources
Written by: Dhanian
📚 Buy my ebooks & code projects: codewithdhanian.gumroad.com
You’re welcome to build upon this project for your school, freelance gigs, or startup.
Top comments (3)
pretty cool seeing the whole thing broken down this way - you ever run into pain points when scaling one of these up past a small school?
Thanks for your feedback lol
Thank you so much for providing exact code snippets for each part of the system! The step-by-step breakdown from setup to React integration is incredibly helpful for someone diving into the MERN stack.