A production-ready, full-stack web application for Islamic education institutions to manage students, teachers, daily attendance, Quran memorisation (Hifz) progress, Sabaq (daily lesson) tracking, examinations, parent communications, and automated reporting — all from a single Progressive Web App.
Built with React 18, TypeScript (strict mode), Firebase, and Tailwind CSS. Deployed on Firebase Hosting with Cloud Functions backend, enforced Firestore security rules, and a hardened Content Security Policy.
- Overview
- Features
- Screenshots
- Tech Stack
- Architecture
- User Roles
- Security
- Getting Started
- Environment Setup
- Project Structure
- Demo Credentials
- Deployment
- Future Improvements
HifzTrack solves a real operational problem for madrasas: tracking hundreds of students' Quran memorisation milestones, daily attendance sessions, and exam results across multiple teachers — without spreadsheets or paper registers.
The system provides four role-based portals (Admin, Teacher, Parent, Student), each scoped to exactly what that user needs. All data access is enforced at the database level through comprehensive Firestore security rules and validated server-side through Cloud Functions.
- Student Management — enrol, edit, assign teachers, view full profiles
- Teacher Management — add teachers, assign student cohorts, view performance
- Attendance — mark morning/evening sessions, view monthly summaries and statistics
- Hifz Tracking — record Quran memorisation milestones per student, analytics
- Sabaq Management — approve or reject daily lesson submissions from students/teachers
- Examinations — create exams, enter results, view analytics per exam
- Reports — generate and export PDF reports: attendance, examination, student progress
- Notifications — broadcast messages to individuals or role groups
- Registration Approvals — review and approve/reject student enrolment requests
- Audit Log — immutable Cloud-Function-written activity trail
- Dashboard scoped to assigned students only
- Mark attendance for own cohort
- Record and review Hifz progress entries
- Review and approve/reject student Sabaq submissions
- Send notifications
- View pending activities and today's Hifz schedule
- View each child's profile and assigned teacher
- Monitor attendance history with monthly summaries
- Track Hifz and Sabaq progress
- View examination results
- Receive notifications from staff
- View personal dashboard, attendance, progress, results
- Submit daily Sabaq entries (pending teacher approval)
- Read notifications
- View own profile
- Progressive Web App — installable on desktop and mobile, offline app-shell
- Auto-update service worker — users always get the latest version
- PDF export — printable reports via jsPDF
- Real-time data — Firestore listeners with optimistic UI updates
- Error boundaries — page-level errors never crash navigation
- Loading skeletons, error-with-retry, and empty states on every data view
- Weekly backup reports — scheduled Cloud Function writes health-check to Firestore
Screenshots can be added here. Run
npm run devand capture the Admin dashboard, Teacher portal, Parent view, and Student portal.
| Admin Dashboard | Hifz Tracker | Parent Portal |
|---|---|---|
| coming soon | coming soon | coming soon |
| Layer | Technology |
|---|---|
| Frontend Framework | React 18 |
| Language | TypeScript 5.5 (strict mode) |
| Build Tool | Vite 5 |
| Styling | Tailwind CSS 3 |
| Routing | React Router DOM 6 |
| Server State | TanStack Query (React Query) v5 |
| Forms & Validation | React Hook Form + Zod |
| Backend / Database | Firebase Firestore |
| Authentication | Firebase Authentication |
| Server Functions | Firebase Cloud Functions (Node.js 20) |
| File Hosting | Firebase Hosting |
| PDF Generation | jsPDF + jsPDF-AutoTable |
| Resend (via Cloud Functions) | |
| PWA | vite-plugin-pwa |
HifzTrack uses feature-based folder architecture with a clear separation of concerns:
- Repository layer — all Firestore CRUD behind a generic
BaseRepository<T>; features extend it for their collection - Service layer — business logic (validation, transformations, side-effects) isolated from UI
- Hook layer — React Query hooks expose typed
{ data, isLoading, error, mutate }to components; components never call Firestore directly - Component layer — purely presentational; receives props from hooks
Cloud Functions handle all privileged operations (role assignment, registration approval, audit writing) via the Admin SDK, so no client-side code can escalate privileges.
src/
├── components/
│ ├── charts/ # Dependency-free chart components
│ ├── feedback/ # Loading skeletons, error states, empty states
│ ├── icons/ # Icon wrappers
│ └── ui/ # Shared UI primitives (Button, Card, Input, Modal…)
├── config/ # Firebase init, environment variable validation
├── features/
│ ├── attendance/ # Mark attendance, history, monthly summary, statistics
│ ├── auth/ # Login, forgot password, auth context
│ ├── dashboard/ # Admin & Teacher dashboards, stat cards
│ ├── exams/ # Exam CRUD, result entry, analytics
│ ├── hifz/ # Hifz record CRUD, analytics
│ ├── notifications/ # Bell, notification list, filters
│ ├── parent/ # Parent portal pages
│ ├── registration/ # Student enrolment requests
│ ├── reports/ # Attendance, exam, progress PDF reports
│ ├── sabaq/ # Sabaq submission and approval workflow
│ ├── students/ # Student list, details, forms
│ ├── studentPortal/ # Student self-service pages
│ ├── teachers/ # Teacher list, details, forms, assignment
│ └── users/ # User role management
├── layouts/ # AuthLayout, DashboardLayout, Sidebar, Topbar
├── lib/ # queryClient, datetime utilities, PDF helpers
├── pages/ # 403 / 404 standalone pages
├── repositories/ # BaseRepository<T>
├── routes/ # AppRouter, ProtectedRoute, RoleRoute, path constants
└── types/ # Shared TypeScript types (roles, etc.)
functions/
└── src/
├── audit/ # Firestore trigger → writes audit log
├── hifz/ # Triggered on Hifz record events
├── registration/ # registerWithCode, approveRegistration, rejectRegistration
├── scheduled/ # weeklyBackupReport cron function
├── users/ # changeUserRole privileged function
└── lib/ # Email (Resend), authorisation helpers, code generation
| Role | Access Scope | How Provisioned |
|---|---|---|
| Admin | Full system access | Firebase Console — set users/{uid}.role = "admin" |
| Teacher | Own assigned cohort only | Admin generates a one-time registration code |
| Parent | Linked children's data only | Admin approves student registration request |
| Student | Own records only | Student submits enrolment request; admin approves |
Routing is guarded by ProtectedRoute (authentication check) and RoleRoute (authorisation check). Each role is redirected to its own dashboard after login.
Account linkages stored in Firestore:
| Field | Document | Description |
|---|---|---|
users/{uid}.role |
users | Role assignment |
students/{id}.userId |
students | Links student portal account |
students/{id}.parentId |
students | Links parent portal account |
students/{id}.teacherId |
students | Assigned teacher document ID |
teachers/{id}.userId |
teachers | Links teacher portal account |
- Default-deny catch-all — unmatched paths are rejected
- Role-based access — every collection gate-checks
users/{uid}.role - Ownership verification — attendance, Hifz, and exam records verify the requesting user owns or teaches the student
- Teacher scope isolation — a teacher can only read/write records for their own assigned cohort; cross-teacher access is blocked
- Privilege escalation prevention —
registrationRequestswrites are validated to ensure the creator cannot set approval fields; approval runs through Cloud Functions (Admin SDK) only - Notification self-service — users can only flip the
readflag on their own notifications; no other fields - Immutable audit log —
auditLogsandbackupReportsare client-write:false; only Cloud Functions write these
Content-Security-Policy default-src 'self'; script-src 'self'; …
X-Content-Type-Options nosniff
X-Frame-Options DENY
Strict-Transport-Security max-age=31536000; includeSubDomains
Referrer-Policy strict-origin-when-cross-origin
Permissions-Policy geolocation=(), camera=(), microphone=()
- Privileged operations (role changes, registration approvals) run exclusively server-side via Admin SDK
- Email API key stored in Firebase Functions Secret Manager (
RESEND_API_KEY), never exposed to clients - All function inputs validated before executing
- All forms validated with Zod schemas before submission
- TypeScript strict mode catches type mismatches at compile time
- Node.js 20+
- npm 9+
- Firebase CLI:
npm install -g firebase-tools - A Firebase project (free Spark plan works for development)
git clone https://github.com/YOUR_USERNAME/hifztrack.git
cd hifztrack
npm installcp .env.example .env.local
# Fill in your Firebase project values (see Environment Setup below)
npm run dev
# Opens at http://localhost:5173| Command | Description |
|---|---|
npm run dev |
Start development server |
npm run build |
Production build |
npm run preview |
Preview production build locally |
npm run typecheck |
TypeScript type check (no emit) |
npm run lint |
ESLint (zero warnings policy) |
npm run build:check |
Typecheck + build (CI-safe) |
Copy .env.example to .env.local and fill in your Firebase project values:
VITE_FIREBASE_API_KEY=your-api-key
VITE_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your-project-id
VITE_FIREBASE_STORAGE_BUCKET=your-project.appspot.com
VITE_FIREBASE_MESSAGING_SENDER_ID=000000000000
VITE_FIREBASE_APP_ID=1:000000000000:web:abcdef123456
VITE_FIREBASE_MEASUREMENT_ID=G-XXXXXXXXXXFind these values in: Firebase Console → Project Settings → Your apps → Web app.
The app validates all required variables at startup and will throw a descriptive error if any are missing.
Cloud Functions email: The Resend API key is stored as a Firebase secret. Set it with:
firebase functions:secrets:set RESEND_API_KEY
These are sample accounts for reviewing the application. Replace with your own Firebase project credentials when self-hosting.
| Role | Password | Access | |
|---|---|---|---|
| Admin | admin@demo.hifztrack.app |
Demo1234! |
Full system |
| Teacher | teacher@demo.hifztrack.app |
Demo1234! |
Assigned cohort |
| Parent | parent@demo.hifztrack.app |
Demo1234! |
Linked children |
| Student | student@demo.hifztrack.app |
Demo1234! |
Own records |
Demo accounts are read-only where appropriate. Student data shown is synthetic — no real personal information is exposed.
See the Architecture section above for the annotated folder tree.
Key design decisions:
- No direct Firestore calls in components — all data access goes through the repository → service → hook pipeline
- Co-located feature code — each feature owns its types, repositories, services, hooks, components, and pages
- Shared primitives only —
src/components/uicontains only reusable, feature-agnostic elements - Environment validation at boot — misconfigured deployments fail fast with clear error messages
See DEPLOYMENT.md for the full step-by-step guide covering:
- Firebase project setup
- Firestore rules and indexes
- Cloud Functions (including secrets)
- Firebase Hosting
- Custom domain configuration
Quick deploy (after setup):
npm run build:check # Typecheck + build
firebase deploy # Rules + indexes + functions + hosting- Fee management module — track tuition payments, generate receipts
- Advanced analytics dashboard — class-level Hifz completion rates, attendance trends
- WhatsApp / SMS notifications — via Twilio or WhatsApp Business API
- Multi-madrasa support — tenant isolation for running multiple institutions
- Offline Hifz entry — IndexedDB sync queue for marking progress without connectivity
- Automated parent progress emails — weekly digest via Cloud Functions scheduler
- Mobile app — React Native with shared Firebase backend
- Unit and integration tests — Vitest + Firebase emulator suite
MIT License — see LICENSE for details.
Built by Faizan Patel