Skip to content
Back to projects

Applicant Workflow Platform

EWS Scholarship Portal

Application intake, document verification, interview scheduling, and merit calculation for a scholarship program.

Deployed — 2025Solo build — pipeline design and merit-scoring logic
Next.jsMongoDBCloudinaryWhatsApp API

Overview

Problem

A scholarship program needed to manage a full applicant lifecycle — application intake, document verification, interviews, and merit-based selection — that had previously been coordinated manually over email and phone, with applicants left guessing about their status.

Solution

An end-to-end applicant portal covering intake, document upload, interview scheduling, and automated merit calculation, with WhatsApp updates so applicants always know where they stand.

Architecture

Client

Applicant-facing intake and status portal, admin review dashboard.

Documents

Cloudinary handling upload, storage, and delivery of applicant documents.

Workflow

Stage-based applicant pipeline: intake → document review → interview → merit → decision.

Messaging

WhatsApp Business API notifying applicants at each stage transition.

Data

MongoDB storing applications, documents metadata, interview records, and merit scores.

  • The applicant record moves through explicit pipeline stages; a WhatsApp notification fires on every stage transition, so status communication is a side effect of the workflow, not a manual task.
  • Merit calculation is a pure function over stored applicant data (documents verified, interview score, eligibility criteria), making it re-runnable and auditable if criteria change.
  • Document uploads go directly to Cloudinary from the client with signed upload parameters, keeping large file traffic off the application server.

Feature Breakdown

  • Applicant intake form with document upload
  • Admin document verification workflow
  • Interview scheduling and scoring
  • Automated merit calculation from eligibility and interview data
  • WhatsApp status updates at every pipeline stage

Implementation Detail

Merit score as a pure, re-runnable function
function calculateMerit(applicant: Applicant): MeritScore {
  const eligibility = scoreEligibility(applicant.income, applicant.category);
  const interview = applicant.interviewScore ?? 0;
  const documents = applicant.documentsVerified ? 1 : 0;
  return {
    total: eligibility * 0.5 + interview * 0.4 + documents * 0.1,
    breakdown: { eligibility, interview, documents },
  };
}

Challenges & Solutions

Applicants had no visibility into where their application stood, which drove repeated manual status inquiries to program staff.

Tied WhatsApp notifications directly to pipeline stage transitions, so status updates go out automatically the moment an application moves forward.

Merit calculation involved multiple weighted factors and needed to be transparent and consistent across a large applicant pool.

Implemented merit scoring as a pure, auditable function over stored applicant data, so results are reproducible and explainable rather than a manual judgment call.

Results

  • Status inquiries to program staff dropped off, since applicants get a WhatsApp update the moment their stage changes rather than needing to ask.
  • Every merit score can be recomputed and explained from the same inputs — during the old email-based process, a challenged decision meant reconstructing it from memory.
  • Documents live in one searchable system instead of scattered across staff inboxes as email attachments.

Lessons Learned

  • Re-running merit scores after a late change to eligibility criteria — something that came up mid-cycle — only worked cleanly because the scoring function had no hidden state to begin with.

Gallery

Screenshots to be added.