Skip to content

About

Team-built recruitment automation platform with CV parsing, ATS scoring, and scheduling

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Swift Hire

Project context: Swift Hire is a FAST-NUCES SE2004 Team 1 project, not a solo project. Contributor roles and the evidence-backed portfolio boundary are recorded in ATTRIBUTION.md.

A dual-driven HR automation platform. Candidates upload CVs; employers type hiring prompts. The system auto-matches, ranks, schedules interviews, and sends reminders — no external AI API.


Tech Stack

Layer Technology
Backend Java 17, Spring Boot 3.2
Auth Spring Security + JWT (jjwt 0.12)
ORM Spring Data JPA + Hibernate
Database MySQL 8
CV Parsing Apache PDFBox 3
Email JavaMail / Gmail SMTP
Scheduler Spring @Scheduled
Frontend React 18 + Vite
Charts Chart.js + react-chartjs-2

Project Structure

swift-hire/
├── backend/                          # Spring Boot (Maven)
│   ├── pom.xml
│   └── src/main/java/com/swifthire/
│       ├── auth/                     # JWT, login, signup, password reset
│       ├── user/model/               # User, Candidate, Employer, Role, AccountStatus
│       ├── user/repository/          # UserRepository, CandidateRepository, EmployerRepository
│       ├── candidate/                # CV upload, PDFBox parser, preferences, matching
│       ├── employer/                 # Employer profile CRUD
│       ├── job/                      # HiringPrompt, JobPosting, PromptEngine, ATS scoring
│       ├── scheduling/               # InterviewWindow, InterviewSlot, ScheduleService
│       ├── automation/               # EmailService (SMTP), ReminderScheduler (cron),
│       │                             # NotificationLog entity + repo (NFR 3.7.3)
│       ├── review/                   # Review model, rate candidate/employer
│       ├── analytics/                # Candidate + Employer analytics APIs
│       ├── admin/                    # Manage users (ban/block), system reports
│       ├── dictionary/               # KnownSkillsDictionary (seed table)
│       ├── config/                   # SecurityConfig, CorsConfig, RateLimitInterceptor
│       └── common/                   # ApiResponse<T>, GlobalExceptionHandler
└── frontend/                         # React + Vite
    └── src/
        ├── api/                      # axios instance + per-module API files
        ├── context/AuthContext.jsx   # JWT storage, login/logout
        ├── components/common/        # ProtectedRoute, StarRating
        ├── pages/auth/               # Login, Signup, ResetPassword, VerifyEmail
        ├── pages/shared/             # MyInterviews (role-aware: candidate + employer)
        ├── pages/candidate/          # Dashboard, Profile, JobPostings, Analytics, RateEmployer
        ├── pages/employer/           # Dashboard, HiringPrompt, RecommendedCandidates,
        │                             # AutoSchedule, RateCandidate, EmployerProfile, Analytics
        └── pages/admin/              # AdminDashboard, ManageUsers (+ Audit Log), SystemReports

Running the App

No extra config needed for testing. Gmail SMTP credentials and DB defaults are already set in application.properties. All tables are auto-created on first run (ddl-auto=update).

Option A — With ngrok (Recommended for cross-device testing)

Verification email links will work on any device, any network (phone, teammate's laptop, etc.).

Prerequisites: Sign up free at ngrok.com → install → authenticate once:

# macOS
brew install ngrok
ngrok config add-authtoken <your-token>

# Windows — download from ngrok.com/download, then:
ngrok config add-authtoken <your-token>

Then just run the launcher script (starts ngrok + backend automatically):

# macOS
bash start-ngrok.sh

# Windows — double-click start-ngrok.bat, or:
start-ngrok.bat

Start frontend normally in a separate terminal: npm run dev


Option B — Local only (same machine, no extra setup)


macOS

1. Start MySQL

brew services start mysql
mysql -u root -e "CREATE DATABASE IF NOT EXISTS swift_hire;"

2. Seed Demo Data + Admin Account (run once after DB is created)

mysql -u root swift_hire < ~/Desktop/swift-hire/seed.sql
# Login: admin@swifthire.com / Admin@1234

3. Start Backend

Maven on macOS defaults to the Homebrew JDK. The JAVA_HOME prefix forces Java 17 — don't skip it.

cd ~/Desktop/swift-hire/backend
JAVA_HOME=/opt/homebrew/opt/openjdk@17 mvn spring-boot:run
# API live at http://localhost:8080

4. Start Frontend

cd ~/Desktop/swift-hire/frontend
npm install   # first time only
npm run dev
# UI live at http://localhost:5173

Windows

1. Start MySQL

Open MySQL Workbench or MySQL Shell and run:

CREATE DATABASE IF NOT EXISTS swift_hire;

Or if MySQL is in your PATH:

mysql -u root -e "CREATE DATABASE IF NOT EXISTS swift_hire;"

2. Seed Demo Data + Admin Account (run once after DB is created)

mysql -u root swift_hire < seed.sql
rem Login: admin@swifthire.com / Admin@1234

3. Start Backend

Open Command Prompt or PowerShell in the backend folder, then:

set JAVA_HOME=C:\Program Files\Java\jdk-17
mvn spring-boot:run

If mvn is not recognized, download Maven and add it to your PATH. Adjust the JAVA_HOME path to wherever Java 17 is installed on your machine.

4. Start Frontend

cd frontend
npm install
npm run dev

Quick Test (confirm backend is up)

curl -s http://localhost:8080/api/auth/login \
  -X POST -H "Content-Type: application/json" \
  -d "{\"email\":\"test@test.com\",\"password\":\"test\"}"
# Expected: {"success":false,"message":"Invalid email or password."}

Team Assignments

Member Roll # Module
Saad Mehmood 24L-3050 BE1: Core/Auth + Admin + DB Schema
[BE2 member] — BE2: Candidate Module (PDFBox, preferences, matching)
[BE3 member] — BE3: Employer Module (Prompt Engine, ATS, JobPostings)
[BE4 member] — BE4: Automation (Auto-Schedule, Cron, Email, Reviews)
[FE1 member] — FE1: Candidate-facing UI
[FE2 member] — FE2: Employer + Admin UI

Use Cases (All 17 Implemented ✅)

UC Name
UC-01 Login (JWT, lockout after 5 failures, role-based redirect)
UC-02 Process Hiring Prompt (Regex NLP, ATS scoring, job posting saved)
UC-03 View Recommended Candidates (ranked by ATS score, profile view)
UC-04 Auto-Schedule Batch (45-min slots, Jitsi Meet links, emails both parties)
UC-05 Rate Candidate (1–5 stars, gated behind COMPLETED slot)
UC-06 Sign Up (password strength via @Pattern, role: CANDIDATE or EMPLOYER)
UC-07 Log Out (JWT cleared client-side, redirect)
UC-08 Manage Candidate Profile
UC-09 Upload CV (PDFBox PDF parsing, skills extracted to DB)
UC-10 Set Preferences (location, shift, job type)
UC-11 View Job Postings (ranked feed for candidate)
UC-12 Rate Employer (1–5 stars, gated behind COMPLETED slot)
UC-13 Manage Users (admin: view, filter, ban/block/activate + audit log)
UC-14 View System Reports + CSV Export
UC-15 Send Interview Reminders (cron 7d/3d/1d, logged to DB)
UC-16 View Hiring Analytics (5+ Chart.js charts)
UC-17 Manage Employer Profile

Key NFRs Implemented

NFR Implementation
Prompt parse ≤3s Regex + in-memory dictionary lookup
CV parse ≤5s PDFBox + word-boundary matching
BCrypt password hashing BCryptPasswordEncoder bean
JWT + configurable expiry jwt.expiry-ms in properties
Email verification on signup (NFR 3.4.4) UUID token, 24h expiry, blocks login until verified
Rate limiting (NFR 3.6.6) Per-IP sliding window: 10 req/min on login, 100 req/min elsewhere → 429
Strong password (NFR 3.8.2) @Pattern regex on SignupRequest
Account lockout after 5 failures (NFR 3.8.4) failedLoginAttempts counter, admin can re-activate
Audit logs for admin actions (NFR 3.8.5) Every approve/block/deactivate logged to audit_logs
Email retry ×3 (NFR 3.7.2) @Retryable(maxAttempts=3) on EmailService
Notification DB log (NFR 3.7.3) NotificationLog entity — SENT/FAILED per reminder
No duplicate reminders (NFR 3.7.5) reminderSent7d/3d/1d flags on InterviewSlot
Archive deleted jobs (NFR 3.9.5) Soft-delete → ARCHIVED status

Dev Notes / Gotchas

  • Maven on macOS: always JAVA_HOME=/opt/homebrew/opt/openjdk@17 mvn <cmd> — Homebrew defaults to latest JDK
  • PDFBox 3.x API: use Loader.loadPDF(byte[]) — PDDocument.load(InputStream) was removed
  • CV parsing regex: use Pattern.find() not String.matches() — multi-line PDF text requires substring search
  • Stale JWT: after a backend restart, log out and back in — old tokens cause 403s without a message field
  • Map.of() with mixed types: use LinkedHashMap with explicit put() — Map.of() infers a complex intersection type incompatible with Map<String, Object>
  • Jitsi Meet links: https://meet.jit.si/swift-hire-<12-char-uid> — no API key needed; DB column still named calendlyLink
  • Cross-device testing (phone/other machine on same WiFi): the email verification link uses localhost by default, which only works on the same machine. To test across devices: find your LAN IP (ipconfig on Windows, ifconfig | grep 192 on macOS), then start the backend with FRONTEND_URL=http://192.168.x.x:5173. Vite already exposes on LAN via host: true in vite.config.js.

About

Team-built recruitment automation platform with CV parsing, ATS scoring, and scheduling

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages