A full-stack placement management platform inspired by Superset β built for college TPOs, students, and recruiters. Features an AI engine that automatically scores and ranks applicants against job descriptions.
Live Demo: https://your-app.vercel.app β replace after deployment
Demo Video: https://youtube.com/your-demo β record after Week 5
| Name | Role | Responsibilities |
|---|---|---|
| [Name 1] | Full-Stack Lead | Backend API, Database, Auth |
| [Name 2] | Frontend Dev | React dashboards, UI/UX |
| [Name 3] | AI/ML Dev | Scoring engine, Resume parser |
| [Name 4] | DevOps | Deployment, Seeding, README |
- Register/login and build a profile (branch, CGPA, skills)
- Upload resume PDF
- Browse open placement drives and apply with one click
- Track application status in real time (Applied β Shortlisted β Selected)
- Receive email + in-app notifications on status change
- Create and manage companies and job drives
- Set eligibility criteria (min CGPA, max backlogs, required skills)
- View analytics dashboard β placement rate, branch-wise stats, drive funnel
- Schedule interview slots and send automated notifications
- Post job descriptions with required skill tags
- View all applicants ranked automatically by AI score
- See skill match breakdown per candidate
- Shortlist candidates and schedule interviews
When a student applies to a drive, the system automatically sends their resume data and the job description to the AI microservice, which returns a score from 0β100.
Scoring formula (weighted):
| Component | Weight | How it's calculated |
|---|---|---|
| Skill match | 50% | matched_skills / required_skills |
| CGPA score | 25% | student_cgpa / 10.0 (normalised) |
| Semantic similarity | 25% | Cosine similarity of resume + JD embeddings via sentence-transformers |
All applicants for a drive are then re-ranked by total score. Recruiters see the ranked list with a colour-coded score bar (green > 70, amber 40β70, red < 40) and a breakdown of which skills matched.
| Layer | Technology |
|---|---|
| Frontend | React 18 + Vite, React Router, React Hook Form, Recharts |
| Backend | Node.js, Express.js, Prisma ORM |
| Database | PostgreSQL (hosted on Railway) |
| AI Service | Python, Flask, pdfplumber, spaCy, sentence-transformers |
| Auth | JWT (JSON Web Tokens), bcryptjs |
| File Storage | Cloudinary (resume PDFs) |
| Nodemailer + Gmail SMTP | |
| Deployment | Vercel (frontend), Render (backend + AI), Railway (DB) |
USERS ββββββββββββ STUDENT_PROFILES
β β
β APPLICATIONS ββββ SHORTLISTS
β β
COMPANIES ββββ JOB_DRIVES ββββ INTERVIEW_SLOTS
USERS ββββ NOTIFICATIONS
Key design decisions:
parsedResumestored as JSON inStudentProfileβ avoids re-parsing on every score requestaiScore+aiRankstored onApplicationβ shortlist sorting is a simpleORDER BY aiRank@@unique([studentId, driveId])on Application β prevents duplicate applications at DB level
placement-portal/
βββ client/ β React + Vite frontend
β βββ src/
β βββ pages/ β Login, StudentDashboard, TPODashboard, RecruiterDashboard
β βββ components/ β DriveCard, ApplicationList, ProfileForm, ScoreBar
β βββ api/ β axios instance with JWT interceptor
β βββ context/ β AuthContext
βββ server/ β Node.js + Express API
β βββ routes/ β auth.js, students.js, drives.js, applications.js
β βββ middleware/ β auth.js (JWT + role guard)
β βββ utils/ β triggerAIScore.js, notify.js
βββ ai/ β Python Flask microservice
β βββ app.py β /score endpoint
β βββ parser.py β PDF text extraction + skill/CGPA extraction
β βββ scorer.py β weighted scoring formula
βββ prisma/
β βββ schema.prisma β all 8 table definitions
β βββ seed.js β 30 students, 5 companies, 8 drives
βββ README.md
- Node.js v18+
- Python 3.10+
- PostgreSQL (or use Railway cloud DB)
git clone https://github.com/your-username/placement-portal.git
cd placement-portalcd server
npm install
cp ../.env.example .env
# Fill in DATABASE_URL, JWT_SECRET, CLOUDINARY_*, EMAIL credentials
npx prisma migrate dev --name init
npx prisma generate
node ../prisma/seed.js # seed dummy data
npm run dev # runs on http://localhost:5000cd ../client
npm install
# Set VITE_API_URL=http://localhost:5000/api in .env.local
npm run dev # runs on http://localhost:5173cd ../ai
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
python -m spacy download en_core_web_sm
python app.py # runs on http://localhost:8000| Role | Password | |
|---|---|---|
| Student | student1@college.edu | password123 |
| TPO | tpo@college.edu | password123 |
| Recruiter | recruiter@tcs.com | password123 |
| Week | Focus | Key Deliverables |
|---|---|---|
| 1 | Project setup + Auth | Monorepo, DB schema, JWT auth, login UI |
| 2 | Profiles + Job drives | Resume upload, apply flow, TPO drive creation |
| 3 | AI engine | Resume parser, scoring formula, Flask microservice |
| 4 | Recruiter dashboard + analytics | Ranked shortlist UI, charts, notifications, interview slots |
| 5 | Polish + deployment | Seed data, Vercel/Render deploy, README, demo video |
| Method | Route | Role | Description |
|---|---|---|---|
| POST | /api/auth/register |
Public | Register new user |
| POST | /api/auth/login |
Public | Login, returns JWT |
| GET | /api/drives |
Student | Get all open drives |
| POST | /api/drives |
TPO | Create a new drive |
| POST | /api/drives/:id/apply |
Student | Apply + trigger AI scoring |
| GET | /api/applications/drive/:id |
Recruiter/TPO | Get ranked applicants |
| PATCH | /api/applications/:id/shortlist |
Recruiter | Shortlist a candidate |
| GET | /api/analytics/summary |
TPO | Placement statistics |
| POST | /score (port 8000) |
Internal | AI scoring microservice |
These are questions you'll likely be asked β prepare answers for them:
-
"Why PostgreSQL and not MongoDB?" β Applications have strict relational integrity (a student can apply to a drive exactly once, shortlists reference applications). Relational DB enforces this at the DB level; MongoDB leaves it to the application code.
-
"Why a separate Python microservice for AI?" β Python has better ML libraries (spaCy, sentence-transformers, scikit-learn). Building it as a microservice means the Node backend just calls an HTTP endpoint β clean separation of concerns and the AI service can be scaled independently.
-
"How does your AI scoring work?" β Walk through the three components: keyword skill match (50%), CGPA normalisation (25%), and semantic cosine similarity using sentence-transformers (25%). Mention the model
all-MiniLM-L6-v2runs in ~50ms on CPU. -
"What if the AI score is biased?" β The recruiter still makes the final shortlist decision. The AI score is a ranking aid, not a binary decision. Recruiters can override by filtering/sorting manually.
-
"How did you handle duplicate applications?" β Prisma
@@unique([studentId, driveId])constraint at the database level β the DB rejects duplicates before any application code runs.
- Branch naming:
feature/your-name/what-you-built(e.g.feature/rahul/ai-scorer) - Commit messages:
feat: add resume parser,fix: JWT expiry,docs: update README - Open a PR to
mainβ get at least one review before merging - Never commit
.envfiles β use.env.examplewith placeholder values
This is a Next.js project bootstrapped with create-next-app.
First, run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun devOpen http://localhost:3000 with your browser to see the result.
You can start editing the page by modifying app/page.tsx. The page auto-updates as you edit the file.
This project uses next/font to automatically optimize and load Geist, a new font family for Vercel.
To learn more about Next.js, take a look at the following resources:
- Next.js Documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
You can check out the Next.js GitHub repository - your feedback and contributions are welcome!
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.
9cc48ee (Initial Next.js project setup)