Ulab One Portal is a production-grade, full-stack academic management system built for the University of Liberal Arts Bangladesh (ULAB). Built with React 18, TypeScript, Node.js 20, Express, and MongoDB, it serves three separate role-specific portals — Student, Teacher, and Admin — each with its own layout, navigation, data layer, and feature set.

Students register via 6-digit OTP email verification (Brevo API), then use a 5-step schedule builder powered by a backtracking algorithm with priority-weighted scoring to generate conflict-free semester timetables. They access a crowd-sourced notes library, upload PDFs stored on Cloudflare R2, and use real-time Socket.io chat with DMs, course group channels, block/unblock contacts, and online presence indicators.

Teachers manage courses end-to-end: enrol students, mark daily attendance (desktop paginated table + mobile tap-to-toggle card list), declare holidays, upload a profile photo, and track per-course analytics with Recharts charts. Admins seed the schedule catalogue from Excel files (SheetJS), manage student/teacher directories, review note submissions with in-browser PDF preview, and configure granular per-admin permissions.

Deployed on a self-managed Linux VPS with PM2 and Nginx reverse proxy. SSL via Let's Encrypt. PDF notes are served directly from Cloudflare R2's public CDN — bypassing the VPS entirely. Live at ulaboneportal.dev.

Client:

Univ. of Liberal Arts Bangladesh

Industry:

Academic / University Portal

Duration:

5+ Months

React 18 TypeScript Node.js 20 Express.js MongoDB Socket.io Cloudflare R2 TanStack Query Tailwind CSS shadcn/ui Vite + SWC Zod + RHF Recharts Framer Motion Brevo (OTP Email) SheetJS (Excel) PM2 + Nginx JWT + bcryptjs

Watch the full project demo and walkthrough

Challenge

The core challenge: build a production-grade university platform serving three very different user types with completely separate feature sets, layouts, and data requirements — from a single unified codebase.

Schedule Builder — Backtracking Algorithm

A 5-step wizard generates the top 3 conflict-free semester timetable variations. The engine groups offered courses by code, derives preferred teachers from Step 2 section picks, re-sorts sections to favour teacher matches, then runs a recursive backtracking search pruning time conflicts instantly using open-interval overlap (a.start < b.end AND b.start < a.end). Safety caps: MAX_VALID = 500, MAX_NODES = 200,000. Each combo is scored on teacher match ratio, gap efficiency, and day compactness — weighted by priority order via triangular descending formula: 3 modes = 50%/33%/17%.

OTP Registration via Brevo

Students submit name, student ID, department, semester, and email. A branded HTML email with a 6-digit OTP is sent via Brevo API with 5-minute in-memory TTL. On verify, account is created and JWT tokens issued. Three separate login endpoints keep role determination unambiguous.

Cloudflare R2 — Memory Pipeline

PDF uploads use Multer memoryStorage → @aws-sdk/client-s3 PutObjectCommand. Files never touch the VPS disk. The returned public CDN URL is stored in MongoDB. Admin rejection calls deleteFromR2() (DeleteObjectCommand), removing the file before the Note document is deleted — zero orphaned files. Max 50MB, PDF only.

Real-Time Chat with Socket.io

Socket.io runs on the same HTTP server as Express. Clients authenticate via JWT in the handshake auth header. Server joins users to DM thread and course group rooms. Online presence tracked with Map<userId, Set<socketId>> — multiple tabs per user handled correctly. Typing indicators, block/unblock, and course group auto-sync fully implemented.

System Design

Frontend Stack

React 18 + TypeScript built with Vite + SWC. Tailwind CSS + shadcn/ui (Radix UI). React Router DOM v6 with StudentRoute / TeacherRoute / AdminRoute guards. TanStack React Query v5 for server state. Axios + JWT interceptors for automatic token refresh on 401. Framer Motion, Recharts, Zod + React Hook Form, Sonner toasts, Embla Carousel, Lucide icons.

Backend Stack

Node.js 20 + Express 4 + TypeScript. JWT: 15min access token (in-memory) + 7d refresh token (httpOnly cookie). protect + authorizeRole middleware on every route. MongoDB 8 via Mongoose with discriminator-based User model (Student, Teacher, Admin). Multer: memoryStorage for R2, diskStorage for avatars. express-rate-limit, Helmet, express-validator, SheetJS, Brevo SDK.

Database Models

User (discriminator base) → Student, Teacher, Admin. Course, OfferedCourse (admin-seeded from Excel; seats decremented atomically), Schedule (student → saved section refs), Attendance (unique index: student+course+date), Holiday, ChatGroup (direct | group), Message, NoteRepository, Note (fileUrl = R2 CDN URL; voters Map<userId, 1|-1>), TeacherDirectory, UploadLog.

Deployment — Self-Managed VPS

Backend compiled to dist/ and managed by PM2. Nginx handles SSL termination (Let's Encrypt), serves Vite dist/ as static, proxies /api and /socket.io to localhost:5000. PDF notes served directly from Cloudflare R2's public CDN — not through the VPS. Teacher avatars served from /uploads on VPS disk. Not deployed on Vercel, Heroku, or any PaaS.

Atomic Seat Reservation

POST /schedule/save-sections has 4 layers: (1) Atomic filter { _id, seats: { $gt: 0 } } — check and decrement in one operation. (2) 409 if Schedule document already exists for student+semester. (3) Partial failure rollback — all decremented seats restored via $inc. (4) Schedule document created linking student to saved sections.

Security

Access token in-memory only. Refresh token in httpOnly cookie. bcryptjs via Mongoose pre-save hook. Rate limiting: 10 req/15min (login), 5 req/15min (OTP). Helmet globally. Strict CORS via CLIENT_URL env. Mongoose hides password via select: false. OTP has 5-min in-memory TTL. R2 credentials only on server — clients receive public CDN URLs, never credentials.

Results

Production-ready university platform live at ulaboneportal.dev, serving students, teachers, and admins with full-feature portals and dedicated mobile-responsive layouts.

Student Portal

Dashboard: GPA, attendance, today's classes, Recent Resources widget (live from DB), Quick Tasks (localStorage). Schedule builder: 5-step wizard, 3 optimized conflict-free variations. Attendance tracker: month-view calendar (present/absent/holiday/no class), subject progress bars, overall stats. Notes library: searchable, department-filtered, PDF upload to R2, upvote/ downvote with trophy badges for top 3 notes. Real-time chat: DMs, course group channels, block/unblock, typing indicators, online presence. Dedicated mobile UI: BottomNav, slide-out MobileMenuDrawer, MobileSchedule.

Teacher Dashboard

KPI overview with Recharts 16-week attendance area chart, engagement radar chart, at-risk student panel. Course grid: per-course stats, syllabus progress bar. Enrolment: search students by name/ID, add/remove from course. Attendance marking: desktop paginated table with mark-all-present; mobile tap-to-toggle card list with fixed Save bar. Holiday management. Profile photo upload. Real-time Socket.io chat with teacher-specific layout.

Admin Panel

KPI dashboard: 7-day traffic chart, enrollment growth, pending approvals queue, color-coded system log feed. Student and teacher directories with search, department filter, pagination, row-level actions. Admin role management with granular per-module permissions. Schedule upload: Excel → preview → confirm to DB with upload logs. Full timetable manager: grid and list views with semester/department/campus filters. Notes review: in-browser PDF preview via R2 URL, approve or reject with feedback. Analytics: 30-day traffic, user distribution donut, department engagement bar. Broadcast messenger. 4-tab settings: General, Branding, Security, API & Integrations.

Key Metrics

Schedule builder generates 3 conflict-free timetable variations in <100ms for 5–6 courses with ~10 sections each. Atomic MongoDB seat reservation prevents race conditions with zero double-booking. Cloudflare R2 CDN delivers PDFs globally with zero VPS load. TanStack React Query provides caching, background refetching, and optimistic updates. TypeScript strict mode on both frontend and backend catches errors at compile time.


I enjoy discussing new university portal projects and academic management system challenges. Please share your educational platform requirements and feature preferences so I can provide the best solution for your learning management needs.