StaySync is a full-stack hostel and PG management platform built for property owners, administrators, and students. It centralizes daily operations such as student onboarding, room allocation, rent tracking, complaints, leave approvals, digital gate pass verification, and announcements into one role-based web application.
The project is structured as a modern MERN-style application with a Next.js frontend and an Express.js backend backed by MongoDB. Redis is used as an optional cache layer for dashboard and reporting data, while Razorpay and SMTP support online rent collection, PDF receipts, and email delivery.
- Project Highlights
- Core Modules
- Tech Stack
- System Architecture
- Folder Structure
- Getting Started
- Environment Variables
- Available Scripts
- API Overview
- Application Workflows
- Data Models
- Security and Reliability
- Deployment Guide
- Troubleshooting
- Future Enhancements
- Role-based authentication for admins and students
- Admin dashboard for rooms, students, revenue, complaints, leaves, and announcements
- Student dashboard for room details, dues, payments, complaints, leaves, and notifications
- Room allocation with occupancy tracking and automatic first payment ledger creation
- Rule-based NLP complaint classification for categories such as Electricity, Water, WiFi, Maintenance, Cleanliness, and Security
- Rent ledger with status tracking for Paid, Pending, and Overdue payments
- Razorpay payment order creation and signature verification
- PDF invoice generation with optional email delivery through SMTP
- Leave request approval flow with QR token generation for gate pass verification
- Public QR verification endpoint for guards/security staff
- Redis-backed caching for frequently accessed statistics and charts
- Protected REST API with JWT Bearer tokens
- Responsive Next.js frontend using Tailwind CSS and reusable dashboard layout components
- Dashboard analytics: View high-level operational metrics for students, rooms, payments, complaints, and leave requests.
- Room management: Create, update, delete, filter, and monitor rooms by floor, capacity, rent, amenities, and occupancy status.
- Student management: View students, update profile/status fields, and remove students when needed.
- Room allocation: Assign students to available rooms, update room occupancy, update the student's assigned room, and generate a pending rent record automatically.
- Complaint management: Review student complaints, filter by status/category, update status, add admin notes, set priority, and track resolution.
- Payment management: Create monthly payment records, update payment status, view revenue stats, view monthly revenue chart data, and download invoices.
- Leave management: Review leave requests, approve/reject requests, add admin notes, and generate QR-enabled gate passes on approval.
- Notifications: Broadcast announcements or targeted messages to students.
- Personal dashboard: Access assigned room details, payments, announcements, and recent activity.
- Complaint submission: Submit complaints with title, description, category, and priority. The backend auto-classifies complaint text as an intelligent default.
- Payment tracking: View personal rent dues, payment history, status, and invoice downloads.
- Online payment support: Initiate Razorpay orders and verify successful transactions.
- Leave applications: Apply for leave with reason, departure date, and return date.
- Digital gate pass: Approved leave requests receive QR tokens that can be verified from a public gate-pass verification page.
- Notifications: Receive announcements and mark messages as read.
| Area | Technology |
|---|---|
| Framework | Next.js 14 with App Router |
| Language | TypeScript |
| UI | React 18 |
| Styling | Tailwind CSS |
| Icons | Lucide React |
| Charts | Recharts |
| QR Rendering | qrcode.react |
| HTTP Client | Axios |
| Notifications | react-hot-toast |
| Date Utilities | date-fns |
| Area | Technology |
|---|---|
| Runtime | Node.js 18+ |
| Framework | Express.js |
| Database | MongoDB |
| ODM | Mongoose |
| Auth | JWT, bcryptjs |
| Validation | express-validator |
| Cache | Redis, optional |
| Payments | Razorpay |
| PDF Generation | PDFKit |
| Nodemailer | |
| Security Middleware | helmet, cors |
| Logging | morgan |
| Compression | compression |
+-----------------------------+
| Next.js Frontend |
| Landing, Auth, Dashboards |
+--------------+--------------+
|
| Axios + JWT Bearer token
v
+-----------------------------+
| Express REST API |
| Auth, Users, Rooms, Payments|
| Complaints, Leaves, Notices |
+-------+-----------+---------+
| |
v v
+--------------+ +--------------+
| MongoDB | | Redis |
| Main storage | | Stats cache |
+--------------+ +--------------+
|
+-- Razorpay payment orders and verification
+-- PDFKit + Nodemailer invoice generation
- A user logs in or registers from the frontend.
- The backend validates credentials and returns a signed JWT.
- The frontend stores the token in
localStorage. - Axios attaches the token as
Authorization: Bearer <token>on protected requests. - Express middleware verifies the token and loads the user from MongoDB.
- Role-based middleware restricts admin-only routes.
- Controllers read/write MongoDB and invalidate Redis cache keys when data changes.
StaySync/
|-- README.md
|-- backend/
| |-- config/
| | |-- db.js
| | `-- redis.js
| |-- controllers/
| | |-- authController.js
| | |-- complaintController.js
| | |-- leaveController.js
| | |-- notificationController.js
| | |-- paymentController.js
| | |-- roomController.js
| | `-- userController.js
| |-- middleware/
| | |-- auth.js
| | `-- error.js
| |-- models/
| | |-- Complaint.js
| | |-- Leave.js
| | |-- Notification.js
| | |-- Payment.js
| | |-- Room.js
| | `-- User.js
| |-- routes/
| | |-- auth.js
| | |-- complaints.js
| | |-- leaves.js
| | |-- notifications.js
| | |-- payments.js
| | |-- rooms.js
| | `-- users.js
| |-- utils/
| | `-- classifier.js
| |-- package.json
| `-- server.js
`-- frontend/
|-- app/
| |-- admin/
| |-- login/
| |-- register/
| |-- student/
| |-- verify-gate-pass/
| |-- globals.css
| |-- layout.tsx
| `-- page.tsx
|-- components/
| |-- layout/
| `-- ProtectedRoute.tsx
|-- context/
| `-- AuthContext.tsx
|-- lib/
| `-- api.ts
|-- package.json
`-- tailwind.config.ts
Install the following before running the project:
- Node.js
18.xor higher - npm
- MongoDB Atlas account or local MongoDB server
- Redis instance, optional but recommended for cached dashboard statistics
- Razorpay account, optional for online payments
- SMTP account, optional for email invoices
git clone <repository-url>
cd StaySynccd backend
npm installCreate a .env file inside backend/:
NODE_ENV=development
PORT=5000
MONGO_URI=mongodb://127.0.0.1:27017/staysync
JWT_SECRET=replace_with_a_strong_secret
JWT_EXPIRE=30d
CLIENT_URL=http://localhost:3000
REDIS_URL=
RAZORPAY_KEY_ID=
RAZORPAY_KEY_SECRET=
SMTP_HOST=
SMTP_PORT=587
SMTP_USER=
SMTP_PASS=Start the backend:
npm run devThe API will run at:
http://localhost:5000/api
Health check:
GET http://localhost:5000/api/health
Open another terminal:
cd frontend
npm installCreate a .env.local file inside frontend/:
NEXT_PUBLIC_API_URL=http://localhost:5000/apiStart the frontend:
npm run devThe app will run at:
http://localhost:3000
| Variable | Required | Description |
|---|---|---|
NODE_ENV |
No | Runtime environment. Use development locally and production in deployment. |
PORT |
No | Backend port. Defaults to 5000. |
MONGO_URI |
Yes | MongoDB connection string. |
JWT_SECRET |
Yes | Secret key used to sign and verify JWTs. |
JWT_EXPIRE |
Yes | JWT expiry value, for example 30d. |
CLIENT_URL |
Recommended | Frontend URL allowed by CORS in production. |
REDIS_URL |
No | Redis connection URL. Supports redis:// and rediss://. App works without Redis using safe no-op cache methods. |
RAZORPAY_KEY_ID |
For online payment | Razorpay key ID used to create payment orders. |
RAZORPAY_KEY_SECRET |
For online payment | Razorpay secret used for order creation and signature verification. |
SMTP_HOST |
For email invoices | SMTP host for sending PDF receipts. |
SMTP_PORT |
For email invoices | SMTP port. Defaults to 587 in code. |
SMTP_USER |
For email invoices | SMTP username/from address. |
SMTP_PASS |
For email invoices | SMTP password or app password. |
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_API_URL |
Recommended | Base API URL used by Axios. Defaults to http://localhost:5000/api. |
Run from backend/:
| Command | Description |
|---|---|
npm run dev |
Starts the Express API with Nodemon. |
npm start |
Starts the Express API with Node. |
Run from frontend/:
| Command | Description |
|---|---|
npm run dev |
Starts the Next.js development server. |
npm run build |
Creates a production build. |
npm start |
Starts the production Next.js server after build. |
npm run lint |
Runs Next.js linting. |
Base URL:
http://localhost:5000/api
Protected endpoints require:
Authorization: Bearer <jwt_token>| Method | Endpoint | Access | Description |
|---|---|---|---|
POST |
/auth/register |
Public | Register a student or admin account. |
POST |
/auth/login |
Public | Login and receive JWT plus user data. |
GET |
/auth/me |
Private | Get current logged-in user with room details. |
| Method | Endpoint | Access | Description |
|---|---|---|---|
GET |
/users/stats |
Admin | Get total and active student counts. |
GET |
/users |
Admin | List users with optional role filter and pagination. |
GET |
/users/:id |
Private | Get a single user. |
PUT |
/users/:id |
Private | Update allowed profile fields. Admin can also update role/status. |
DELETE |
/users/:id |
Admin | Delete user and remove them from allocated room if needed. |
| Method | Endpoint | Access | Description |
|---|---|---|---|
GET |
/rooms/stats |
Admin | Get room totals by status. |
GET |
/rooms |
Private | List rooms. Supports status and floor query filters. |
POST |
/rooms |
Admin | Create a room. |
GET |
/rooms/:id |
Private | Get one room with assigned students. |
PUT |
/rooms/:id |
Admin | Update room data. |
DELETE |
/rooms/:id |
Admin | Delete room only if not occupied. |
POST |
/rooms/:id/allocate |
Admin | Allocate a student to a room and generate initial payment record. |
POST |
/rooms/:id/deallocate |
Admin | Remove a student from a room. |
| Method | Endpoint | Access | Description |
|---|---|---|---|
GET |
/complaints/stats |
Private | Get complaint statistics. Admin sees global stats, students see own stats. |
GET |
/complaints |
Private | List complaints. Supports status, category, page, and limit. |
POST |
/complaints |
Private | Create complaint with automatic category classification. |
GET |
/complaints/:id |
Private | Get one complaint. Students can only access their own complaint. |
PUT |
/complaints/:id |
Private | Admin updates status/note/priority; student can edit pending complaint description. |
DELETE |
/complaints/:id |
Private | Delete complaint with ownership checks. |
| Method | Endpoint | Access | Description |
|---|---|---|---|
GET |
/payments/stats |
Private | Get paid, pending, overdue, and revenue stats. |
GET |
/payments/revenue-chart |
Private | Get monthly revenue chart data. |
GET |
/payments |
Private | List payments. Students see their own payments; admins can filter by student/status/month/year. |
POST |
/payments |
Admin | Create a payment record. |
PUT |
/payments/:id |
Admin | Update status, method, transaction ID, and notes. |
POST |
/payments/:id/create-order |
Private | Create a Razorpay order for a payment. |
POST |
/payments/verify |
Private | Verify Razorpay signature and mark payment as paid. |
GET |
/payments/:id/invoice |
Private | Download a PDF invoice for a paid payment. |
| Method | Endpoint | Access | Description |
|---|---|---|---|
GET |
/notifications |
Private | Get sent notifications for admin or received notifications for student. |
POST |
/notifications |
Admin | Create announcement or targeted notification. |
PUT |
/notifications/read-all |
Private | Mark all accessible notifications as read. |
PUT |
/notifications/:id/read |
Private | Mark one notification as read. |
DELETE |
/notifications/:id |
Private | Delete notification if admin or sender is authorized. |
| Method | Endpoint | Access | Description |
|---|---|---|---|
GET |
/leaves/verify/:token |
Public | Verify QR gate pass token. |
GET |
/leaves/stats |
Admin | Get leave counts by status. |
GET |
/leaves/my-leaves |
Private | Get current student's leave requests. |
POST |
/leaves/apply |
Private | Apply for leave. |
GET |
/leaves |
Admin | List all leave requests. Supports status query filter. |
PATCH |
/leaves/:id/status |
Admin | Approve or reject a leave request. Approval generates QR token. |
- User registers or logs in.
- Backend validates credentials and returns a JWT.
- Frontend stores token in
localStorage. AuthContextloads the user through/auth/meon app start.- Users are redirected to
/admin/dashboardor/student/dashboardaccording to role.
- Admin creates rooms with capacity, floor, type, rent, and amenities.
- Admin selects a student and allocates them to a room.
- Backend checks room availability.
- If the student already has a room, they are removed from the old room.
- Student is added to the new room.
- Room occupancy and status are recalculated.
- A pending payment record is created for the current month.
- Room and payment cache keys are invalidated.
- Student submits a complaint title and description.
- Backend combines title and description and passes them to the classifier.
- The classifier checks keyword matches across known categories.
- Complaint is saved with both selected/final category and auto-classified category.
- Admin reviews and updates status, priority, and admin notes.
- Complaint statistics cache is invalidated on changes.
- Payment records are created manually by admin or automatically during room allocation.
- Student can view pending payments.
- For online payment, backend creates a Razorpay order.
- After payment, Razorpay details are sent to
/payments/verify. - Backend validates the HMAC signature.
- Payment is marked as
Paid, transaction ID is stored, andpaidAtis set. - PDF receipt is generated with PDFKit.
- If SMTP is configured, invoice is emailed to the student.
- Student applies for leave with reason, departure date, and return date.
- Backend validates that return date is after departure date.
- Admin approves or rejects the request.
- On approval, a unique QR token is generated.
- Student dashboard can render QR gate pass.
- Security staff can scan/open the public verification URL.
- Backend validates token, approval status, and date range.
- First successful scan stores
qrScannedAt.
Stores account and profile details:
name,email,passwordrole:studentoradminphoneroomprofileImageisActive
Passwords are hashed using bcrypt before saving. JWT payload contains the user ID and role.
Stores accommodation details:
roomNumberfloortype:Single,Double,Triple,Dormitorycapacityoccupiedstudentsrentamenitiesstatus:Available,Occupied,Full,Maintenancedescription
Room status is recalculated before save based on occupancy and capacity.
Stores student complaints:
studenttitledescriptioncategoryautoCategorystatus:Pending,In Progress,Resolved,Rejectedpriority:Low,Medium,HighadminNoteresolvedAtroom
Stores rent ledger records:
studentroomamountmonthyearstatus:Paid,Pending,OverduepaymentMethod:Cash,Online,UPI,Bank TransfertransactionIdpaidAtdueDatenotes
Pending payments automatically become overdue on save if the due date has passed.
Stores student leave requests:
studentreasondepartureDatereturnDatestatus:Pending,Approved,RejectedadminNoteqrTokenqrScannedAtapprovedBy
The model validates that return date must be after departure date.
Stores announcements and messages:
titlemessagetype:Announcement,Complaint,Payment,Room,GeneralsentByrecipients:allor comma-separated user IDsreadBy
- Passwords are hashed with bcrypt before storing.
- Protected API routes require JWT Bearer tokens.
- Admin-only actions are guarded with role authorization middleware.
- CORS restricts production origins through
CLIENT_URL. - Helmet sets security-related HTTP headers.
- Express request bodies are parsed safely through JSON and URL-encoded middleware.
- Centralized error middleware normalizes error responses.
- Redis is optional and wrapped in a safe proxy so the app continues running when Redis is unavailable.
- Cache invalidation happens after mutations to rooms, users, payments, complaints, and leaves.
- Razorpay payment verification uses HMAC SHA-256 signature comparison.
- Gate pass verification validates token existence, approval status, and date range.
Recommended platforms:
- Render
- Railway
- Fly.io
- VPS with Node.js and PM2
Typical backend settings:
Root Directory: backend
Build Command: npm install
Start Command: npm start
Required production environment variables:
NODE_ENV=production
PORT=5000
MONGO_URI=<mongodb-atlas-uri>
JWT_SECRET=<strong-secret>
JWT_EXPIRE=30d
CLIENT_URL=https://your-frontend-domain.comOptional production integrations:
REDIS_URL=<redis-or-rediss-url>
RAZORPAY_KEY_ID=<razorpay-key-id>
RAZORPAY_KEY_SECRET=<razorpay-key-secret>
SMTP_HOST=<smtp-host>
SMTP_PORT=587
SMTP_USER=<smtp-user>
SMTP_PASS=<smtp-password>Recommended platform:
- Vercel
Typical frontend settings:
Root Directory: frontend
Framework Preset: Next.js
Build Command: npm run build
Output: .next
Frontend environment variable:
NEXT_PUBLIC_API_URL=https://your-backend-domain.com/api- Use a strong
JWT_SECRET. - Set
NODE_ENV=production. - Set
CLIENT_URLto the exact frontend domain. - Use MongoDB Atlas or a secure managed MongoDB instance.
- Configure Redis only if a stable Redis provider is available.
- Configure Razorpay keys only on the backend.
- Configure SMTP credentials if invoice emails are required.
- Ensure frontend
NEXT_PUBLIC_API_URLpoints to the deployed backend/apiURL. - Test login, room allocation, payment verification, invoice download, and gate pass verification after deployment.
Check:
MONGO_URIis present inbackend/.env.- MongoDB server is running if using local MongoDB.
- MongoDB Atlas IP allowlist includes your deployment/server IP.
- Username and password in the connection string are correct.
Check:
- Backend is running on
http://localhost:5000. - Frontend has
NEXT_PUBLIC_API_URL=http://localhost:5000/api. - In production, backend
CLIENT_URLexactly matches the frontend domain. - Browser console is not showing CORS errors.
Check:
- User is logged in.
- Token exists in
localStorage. JWT_SECREThas not changed after token generation.- The request includes
Authorization: Bearer <token>.
If REDIS_URL is missing, the backend logs a warning and continues without cache. This is expected in local development.
Add both:
RAZORPAY_KEY_ID=
RAZORPAY_KEY_SECRET=Restart the backend after updating .env.
Check:
SMTP_HOST,SMTP_PORT,SMTP_USER, andSMTP_PASSare configured.- The SMTP provider allows app passwords or SMTP access.
- Payment was successfully verified and marked as paid.
If SMTP is not configured, the invoice PDF is still generated locally by the backend when possible.
- Super admin and multi-property support
- Dedicated staff roles for maintenance, security, and accounts
- Real-time notifications with WebSockets
- Advanced complaint assignment and SLA tracking
- Automated recurring monthly rent generation
- Payment webhooks for stronger payment reconciliation
- File uploads for complaint images and profile photos
- Email/SMS alerts for leave approvals, dues, and announcements
- Audit logs for admin actions
- Unit, integration, and end-to-end test coverage
- Docker Compose setup for local MongoDB, Redis, backend, and frontend
Developed by Anurag Kumar.
StaySync is designed as a professional full-stack project for modern hostel and PG operations, combining clean dashboards, practical admin workflows, student self-service, and reliable backend APIs.