Live Deployed Link --> https://societymaintancetracker.onrender.com/
A full-stack, enterprise-grade apartment society maintenance management platform built with Next.js 14/15 (TypeScript, React, Tailwind CSS) and Prisma ORM.
The platform bridges communication between apartment residents and society administration, providing transparent complaint lifecycle tracking, dynamic overdue escalation, photo evidence attachments, pinned society notices, and automated email updates.
- Key Features
- Tech Stack
- Quickstart & Local Setup
- Pre-Seeded Demo Accounts
- Environment Variables (
.env.example) - Database Schema & ER Model
- Comprehensive API Documentation
- System Design Highlights
- Deployment Guide (Vercel / Render / Railway)
- Packaging & Deliverables
-
Role-Based Access Control (RBAC): Distinct permissions and workflows for
RESIDENTandADMINusers. -
Complaint Lifecycle & Audit Trail: Full state transitions (
OPEN$\rightarrow$ IN_PROGRESS$\rightarrow$ RESOLVED) with immutable timestamped logs capturing actor name, role, and action notes. - Dynamic Overdue Escalation: Configurable threshold days; overdue complaints bubble to the top of the admin triage queue with visual alerts.
- Photo Evidence Pipeline: Drag-and-drop file upload with preview, file size/type validation, and full-resolution lightbox viewer.
- Notice Board & Broadcast System: Pinned important notices with automatic email dispatch to all registered residents.
-
Dual-Mode Notification Engine: Supports live SMTP delivery and includes a built-in In-App Outbox Inspector (
/admin/outbox) for immediate evaluation without external SMTP credentials. - Admin Analytics Dashboard: Real-time KPI summary cards, facility category breakdown charts (Recharts), and status distributions.
| Layer | Technology |
|---|---|
| Framework | Next.js 14/15 (App Router, TypeScript) |
| Frontend UI | React 18/19, Tailwind CSS, Lucide Icons |
| Charts & Visuals | Recharts Data Visualizations |
| ORM & Database | Prisma ORM with SQLite (Local) / PostgreSQL (Production) |
| Auth & Security | JWT (JSON Web Tokens), bcryptjs password hashing |
| Notifications | Nodemailer (SMTP) + Database Outbox Logger |
- Node.js 18.x or 20.x+
- npm or yarn
git clone <repository-url>
cd society-maintenance-tracker
npm installCopy the example environment file:
cp .env.example .envRun Prisma migrations and populate the database with realistic test data (admins, residents, active/overdue complaints, notices, audit history):
npx prisma db push
npm run prisma:seednpm run devOpen http://localhost:3000 in your browser.
The database comes pre-populated with ready-to-test accounts. You can also use the 1-Click Quick Demo Login buttons on the login page:
| Role | Password | Details | |
|---|---|---|---|
| Estate Admin | admin@society.com |
Admin@123 |
Full admin privileges, overdue controls, outbox logs |
| Resident 1 | john.doe@society.com |
Resident@123 |
John Doe (Flat A-101) - Has active/overdue plumbing ticket |
| Resident 2 | jane.smith@society.com |
Resident@123 |
Jane Smith (Flat B-204) - Has elevator ticket |
| Resident 3 | robert.chen@society.com |
Resident@123 |
Robert Chen (Flat C-305) - Has electrical ticket |
# Database Connection (SQLite default for zero-setup local dev; change to postgresql:// for production)
DATABASE_URL="file:./dev.db"
# JWT Secret for Session Signing
JWT_SECRET="society_maintenance_tracker_jwt_secret_key_2026_unthinkable"
# Base Application URL
NEXT_PUBLIC_APP_URL="http://localhost:3000"
# Optional SMTP Settings (If omitted, emails are logged to the in-app outbox inspector at /admin/outbox)
SMTP_HOST=""
SMTP_PORT="587"
SMTP_USER=""
SMTP_PASS=""
SMTP_FROM="Society Admin <noreply@societytracker.com>"
# Default Overdue Threshold (Days)
DEFAULT_OVERDUE_DAYS="3"┌────────────────────────────────┐ 1:N ┌──────────────────────────────┐
│ User ├─────────────────►│ Complaint │
├────────────────────────────────┤ ├──────────────────────────────┤
│ id (PK) │ │ id (PK) │
│ name │ │ ticketNumber (UK) │
│ email (UK) │ │ title │
│ password (Hash) │ │ description │
│ role (RESIDENT | ADMIN) │ │ category (PLUMBING, etc.) │
│ flatNumber │ │ priority (LOW, MEDIUM, HIGH) │
│ phoneNumber │ │ status (OPEN, IN_PROGRESS, │
│ createdAt / updatedAt │ │ RESOLVED) │
└───────┬───────────────────┬────┘ │ photoUrl │
│ │ │ residentId (FK) │
│ 1:N │ 1:N │ createdAt / resolvedAt │
▼ ▼ └──────────────┬───────────────┘
┌───────────────┐ ┌──────────────────────────────┐ │ 1:N
│ Notice │ │ ComplaintStatusHistory │◄─────────────┘
├───────────────┤ ├──────────────────────────────┤
│ id (PK) │ │ id (PK) │
│ title │ │ complaintId (FK) │
│ content │ │ fromStatus │
│ isImportant │ │ toStatus │
│ authorId (FK) │ │ actorId (FK) │
│ createdAt │ │ actorName │
└───────────────┘ │ actorRole │
│ note │
│ createdAt │
└──────────────────────────────┘
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ SystemSetting │ │ EmailLog │
├──────────────────────────────┤ ├──────────────────────────────┤
│ id (PK) │ │ id (PK) │
│ key (UK, e.g. OVERDUE_DAYS) │ │ recipientEmail / Name │
│ value │ │ subject │
│ description │ │ type (STATUS_CHANGE, etc.) │
│ updatedAt │ │ contentHtml │
└──────────────────────────────┘ │ status (SENT | SIMULATED) │
│ createdAt │
└──────────────────────────────┘
Registers a new resident or admin account.
- Request Body:
{ "name": "Alex Morgan", "email": "alex@society.com", "password": "Password@123", "role": "RESIDENT", "flatNumber": "A-502", "phoneNumber": "+1 555-0199" } - Response
(201 Created):{ "message": "Registration successful", "user": { "id": "...", "name": "Alex Morgan", "email": "alex@society.com", "role": "RESIDENT" }, "token": "eyJhbGciOiJIUzI1NiIs..." }
Authenticates a user and returns a signed JWT token (also sets HTTP-only cookie).
- Request Body:
{ "email": "admin@society.com", "password": "Admin@123" }
Fetches authenticated user profile from active session.
Clears authentication cookie and terminates session.
Fetches complaints. If accessed by a resident, returns only their own complaints. If accessed by an admin, returns all society complaints with overdue tickets surfaced at the top.
- Query Parameters:
category(PLUMBING,ELECTRICAL,ELEVATOR,SECURITY,CLEANLINESS,CARPENTRY,OTHER,ALL)status(OPEN,IN_PROGRESS,RESOLVED,ALL)search(Search by ticket number, title, or resident details)dateFrom/dateTo(YYYY-MM-DDrange)overdueOnly(true/false)
- Sample Response:
{ "complaints": [ { "id": "clx123", "ticketNumber": "CMP-2026-0001", "title": "Kitchen pipe leaking", "category": "PLUMBING", "priority": "HIGH", "status": "OPEN", "photoUrl": "/uploads/complaint_1.jpg", "isOverdue": true, "daysOpen": 5, "createdAt": "2026-08-17T10:00:00.000Z", "resident": { "name": "John Doe", "flatNumber": "A-101" } } ], "thresholdDays": 3, "count": 1 }
Raises a new complaint (Resident only).
- Request Body:
{ "title": "Corridor light fixture broken", "description": "Hallway light outside flat 204 is non-functional.", "category": "ELECTRICAL", "photoUrl": "/uploads/photo_123.jpg" }
Retrieves detailed complaint information including full chronological lifecycle audit trail.
Updates status and priority with mandatory audit logging (Admin only).
- Request Body:
{ "status": "IN_PROGRESS", "priority": "HIGH", "note": "Electrician team dispatched with replacement ballast." } - Triggers asynchronous email notification to the resident.
Retrieves all society notices. Pinned important notices are ordered first.
Publishes a new society notice (Admin only).
- Request Body:
{ "title": "⚡ Scheduled Power Maintenance This Saturday", "content": "Power maintenance will be carried out between 10 AM and 2 PM.", "isImportant": true } - Setting
isImportant: truepins the notice to the top and triggers an email broadcast to all residents.
Returns current system settings (e.g., overdueThresholdDays).
Updates overdue threshold in days (Admin only).
- Request Body:
{ "overdueThresholdDays": 5 }
Returns aggregated analytics metrics (Admin only):
- Total, Open, In Progress, Resolved, and Overdue complaint counts.
- Facility breakdown by category and priority.
- Recent audit history feed.
Accepts multipart/form-data image file upload (image/jpeg, image/png, image/webp), validates
Returns the recent notification outbox log for in-browser inspection.
Refer to SYSTEM_DESIGN.md for the complete 800-word architectural write-up covering:
- Complaint History Model: Event-sourced audit logging with atomic transaction integrity.
- Overdue Detection: Dynamic SLA calculation and queue bubbling.
- Photo Asset Pipeline: Secure MIME verification, sanitized storage, and lightbox viewing.
- Notification Architecture: Dual-mode SMTP delivery with fallback database logging.
- Push repository to GitHub.
- Import project into Vercel.
- Under Environment Variables, set:
DATABASE_URL: Your PostgreSQL / Supabase / Neon connection string.JWT_SECRET: A secure random 32-character string.NEXT_PUBLIC_APP_URL: Your production Vercel domain.
- Set Build Command:
prisma generate && next build. - Deploy!
- Create a new Web Service connecting to your GitHub repository.
- Select Node.js environment.
- Set Build Command:
npm install && npx prisma generate && npm run build. - Set Start Command:
npm start. - Add PostgreSQL database and link
DATABASE_URL.
To generate the standalone submission archive:
npm run package:zipThis produces society-maintenance-tracker.zip containing all clean source code, configuration files, and documentation.