AB
Full StackLive & Deployed

LUMS Navigator

LUMS Navigator brings together the most important aspects of student life into a single platform. Built with Next.js 15 and an Express.js backend, it uses a two-tier verification system — any user can browse public content (societies, eateries), but LUMS-exclusive features (polls, budget tracker, course swap, AI chatbot) are gated behind LUMS email OTP verification. The RAG-based chatbot answers questions directly from the Student Handbook or any uploaded PDF, with persistent chat history per user.

The Problem

LUMS students had no single place to manage their campus life. Information about societies, eateries, and course swaps was scattered across WhatsApp groups, Facebook pages, and word of mouth. The Student Handbook — a dense PDF most students never read — contained answers to hundreds of common questions but was impossible to search. LUMS Navigator was built to consolidate all of this: a platform where students can find what they need, connect with each other, and get instant answers from an AI that actually knows the university.

Key Engineering Decisions

01

Two-Tier Verification over Role-Based Auth

Rather than a full RBAC system, a simple isVerified flag on the User model combined with a requireVerified middleware cleanly separates public and LUMS-exclusive routes — less complexity, same security boundary.

02

OTP over SSO for LUMS Verification

LUMS doesn't expose a public SSO endpoint, so email OTP to the student's @lums.edu.pk address was the most reliable way to prove university affiliation. OTPs are hashed in MongoDB with a TTL index for automatic expiry — no cron jobs needed.

03

RAG over Fine-Tuning for the Chatbot

The Student Handbook changes yearly and uploads are user-driven — fine-tuning a model would be stale within months. RAG with pdf-parse for document ingestion means the chatbot always answers from the current source without retraining.

04

Clerk for Auth Instead of Custom JWT

Clerk handles Google OAuth, email sign-in, webhook user sync to MongoDB, and token validation in the Express middleware — removing an entire authentication layer that would have taken weeks to build securely from scratch.

05

Mongoose TTL Index for OTP Expiry

OTP documents self-delete at their expiry timestamp via a MongoDB TTL index, keeping the collection clean without any scheduled cleanup jobs or background workers.

06

Monorepo with Independent Deployments

Frontend and backend live in the same repository but deploy independently — Vercel watches the frontend/ directory, Railway watches backend/. This keeps PRs coherent while allowing each service to scale and deploy on its own schedule.

Key Highlights

  • Two-tier auth system: Clerk for sign-in (Google OAuth + email), plus LUMS email OTP verification gating exclusive features via requireVerified middleware.
  • RAG-based AI chatbot powered by OpenAI API — answers questions from the LUMS Student Handbook or uploaded PDF documents, with persistent per-user chat history.
  • Course Swap Marketplace — post and browse swap requests with full schedule details; express interest directly on listings.
  • Personal Budget Tracker with monthly expense categories, pie charts, spending trends, and budget vs. actual analytics via Recharts.
  • Community Polls — create and vote on polls with configurable duration, anonymous voting, and comment threads.
  • Societies & Eateries directories with filtering, reviews, ratings, menus, and event listings.
  • Monorepo: Next.js 15 frontend on Vercel, Express.js + MongoDB backend on Railway, MongoDB Atlas cloud database.

Tech Stack

Next.js 15TypeScriptExpress.jsMongoDBClerkOpenAI APIRAGTailwind CSSRadix UIRechartsVercelRailway

Key Takeaways

Two-tier access control (authenticated vs. verified) is a cleaner model than generic RBAC when your access boundary maps to a single real-world criterion — LUMS email ownership in this case.

RAG quality depends heavily on chunking strategy — splitting the Student Handbook by section rather than fixed token windows dramatically improved the chatbot's ability to retrieve the right passage.

Clerk webhooks are the correct sync mechanism between Clerk and your database, but they require careful idempotency handling: webhooks can fire more than once, and a missing duplicate check will create ghost users.

Building a course swap marketplace taught me that the hard part isn't the CRUD — it's the state machine: a swap request moves through posted → interested → confirmed → closed, and each transition needs to be atomic to avoid double-booking.

Recharts is simple to get working but requires careful data shaping on the server side — sending pre-aggregated monthly summaries rather than raw expense arrays kept chart rendering fast even for users with large histories.

Separating protected and verified route groups in Next.js App Router from the start made it trivial to add new features to the right access tier without touching existing middleware.