Skip to content

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JobTrack - Job Application Management System

A secure, stateless REST API backend built with Java 17, Spring Boot 3.3.2, and MongoDB to help job seekers track, filter, organize, and manage their job applications and recruitment pipelines.


1. Problem Statement

During a job search, candidates apply to dozens of roles across different companies, portals, and platforms (LinkedIn, referral, career pages). Keeping track of different stages (Online Assessments, Technical Rounds, HR Interviews), scheduled dates, custom recruitment pipelines, application statuses, and notes in spreadsheets is static, error-prone, and lacks real-time integrations.

2. Project Objective

The objective of JobTrack is to provide a unified, secure, and user-scoped tracking tool that:

  • Secures candidate data with stateless token-based authorization.
  • Isolates data so users can only access their own applications.
  • Accommodates dynamic company-specific interview pipelines (custom stages).
  • Enables search, filtering, and sorting to organize applications.
  • Provides statistics and conversion rates (interview rates, offer rates).

3. Features

  • Stateless JWT Authentication: Secure user registration, password hashing (BCrypt), and stateless session JWT logins.
  • Core CRUD Scoped to User: Add, read, update, and delete job applications with strict ownership boundaries.
  • Recruitment Lifecycle & Stage Management:
    • Creates a default 5-stage pipeline (Applied -> OA -> Technical Interview -> HR Interview -> Offer) if no custom stages are supplied.
    • Allows defining custom stage pipelines during application creation.
    • Supports adding, editing, and deleting custom stages.
    • Stage transition tracking: marking current stages, skipping intermediate rounds, and completing pipelines.
  • Search, Filter & Paginate:
    • Case-insensitive keyword search matching company name or role.
    • Filters by status (ACTIVE, REJECTED, WITHDRAWN), current stage, source, and applied date ranges.
    • Supports custom sorting properties and directions.
  • Statistics Dashboard:
    • Tracks counts for total, active, rejected, and withdrawn applications.
    • Tracks current application distribution across stages.
    • Computes and rounds interview rates and offer rates to exactly 2 decimal places.

4. Tech Stack

Backend

  • Language: Java 17 (OpenJDK 17)
  • Framework: Spring Boot 3.3.2
    • Spring Security: Authentication & Authorization (stateless JWT)
    • Spring Data MongoDB: Object-Document Mapping (ODM)
    • Jakarta Validation: Request validation constraints
  • Database: MongoDB (Local or Atlas)
  • Libraries:
    • io.jsonwebtoken (jjwt): Token signature checks
    • Springdoc OpenAPI: Interactive Swagger UI documentation
  • Testing: JUnit 5, Mockito, Spring Security Test, MockMvc

Frontend

  • Core: React 19 (TypeScript)
  • Build Tool: Vite 8, PostCSS
  • Styling: Tailwind CSS v4
  • HTTP Client: Axios (configured with token request interceptors & auth event listeners)
  • Routing: React Router v7 (SPA routing)

5. Folder Structure

Job-Tracker/
├── src/                                # Spring Boot backend source files
│   ├── main/
│   │   ├── java/com/jobtrack/
│   │   │   ├── config/                 # Security, CORS, & Swagger configurations
│   │   │   ├── controller/             # REST endpoints (Auth, Application, Stats, Health)
│   │   │   ├── dto/                    # Request & Response DTO records
│   │   │   ├── exception/              # Custom Exceptions & GlobalExceptionHandler
│   │   │   ├── model/                  # Database Models (User, JobApplication)
│   │   │   ├── repository/             # Spring Data repositories
│   │   │   ├── security/               # Custom filter & UserDetails implementation
│   │   │   └── service/                # Core business logic services
│   │   └── resources/
│   │       └── application.yml         # Environment-based YAML config
│   └── test/                           # JUnit 5 integration & controller MockMvc tests
├── frontend/                           # React Vite TypeScript frontend files
│   ├── src/                            # React code (pages, components, api clients, context)
│   ├── public/                         # Public assets (briefcase SVG favicon)
│   ├── vercel.json                     # Client-side SPA routing rewrites for Vercel
│   ├── package.json                    # Frontend package dependencies
│   ├── .env.example                    # Frontend environment configuration template
│   └── .gitignore                      # Exclusions list for node modules and env secrets
├── Dockerfile                          # Multi-stage Docker config for Render
├── .dockerignore                       # Docker folder exclusions
├── .env.example                        # Root env variables template
├── .gitignore                          # Root git ignore rules
├── pom.xml                             # Maven POM dependency map
└── README.md                           # Documentation

6. Architecture & System Design

Local Architecture

graph TD
    Browser[Client Browser] -->|http://localhost:5173| Frontend[Vite React Frontend]
    Frontend -->|http://localhost:8081/api| Backend[Spring Boot Backend]
    Backend -->|mongodb://localhost:27017| LocalDB[(Local MongoDB)]
Loading

Production Architecture

graph TD
    Browser[Client Browser] -->|HTTPS| Frontend[Vercel Hosted Client]
    Frontend -->|HTTPS REST API| Backend[Render Hosted Container]
    Backend -->|Atlas Driver Protocol| CloudDB[(MongoDB Atlas Cluster)]
Loading

Authentication Flow

  1. Register: Client registers with name, email, and password. The API checks for duplicate emails, hashes the password via BCrypt, and saves a User document.
  2. Login: Client logins with email and password. The API matches credentials, generates a HS256-signed JWT token, and returns it with a 200 OK.
  3. Secure Request: The client attaches Authorization: Bearer <token> to headers. The JwtAuthenticationFilter interceptor validates the token, extracts the user ID, loads the user details principal, and loads them into the security context.

Recruitment Lifecycle & Stage Design

  • Each JobApplication maintains an ordered list of ApplicationStage sub-documents.
  • Default Pipeline:
    [1] Applied (CURRENT) -> [2] OA (PENDING) -> [3] Technical Interview (PENDING) -> [4] HR Interview (PENDING) -> [5] Offer (PENDING)
    
  • Transitions: Advancing to a stage updates the target to CURRENT and marks the previous stage as COMPLETED. Any intermediate stages between the old and new stage order that were PENDING are marked as SKIPPED (e.g. going from Applied to Technical Interview automatically marks OA as SKIPPED).
  • Outcome updates: The status of an application can be set to ACTIVE, REJECTED, or WITHDRAWN via a dedicated endpoint, which changes the top-level application outcome without altering the stage pipeline state.

7. API Endpoints Table

Method Endpoint Purpose Auth Required
POST /api/auth/register Register a new user account No
POST /api/auth/login Log in and retrieve JWT Bearer token No
GET /api/users/me Fetch authenticated user profile details Yes
GET /api/health Public service health check status No
POST /api/applications Create a new job application Yes
GET /api/applications List, search, filter, sort, and paginate applications Yes
GET /api/applications/{id} Fetch full details of a specific job application Yes
PUT /api/applications/{id} Update basic details of a job application Yes
DELETE /api/applications/{id} Delete a job application Yes
PATCH /api/applications/{id}/outcome Update application outcome status Yes
PATCH /api/applications/{id}/stage Transition active stage to target stage Yes
POST /api/applications/{id}/stages Add a new custom stage to the application Yes
PATCH /api/applications/{id}/stages/{stageId} Update details of a specific stage Yes
DELETE /api/applications/{id}/stages/{stageId} Delete a custom stage from the application Yes
GET /api/applications/stats Retrieve job-search statistics and rates Yes

8. Setup & Run Instructions (Local Development)

1. Backend Local Setup

  1. Create a .env file in the project root directory:
    MONGODB_URI=mongodb://localhost:27017
    MONGODB_DATABASE=jobtrack
    JWT_SECRET=403b472b535d4e138a0fdfebadcf626788b7762671239aa8de6739bcbcad2341
    JWT_EXPIRATION=86400000
    PORT=8081
    FRONTEND_URL=http://localhost:5173
  2. Start MongoDB Server locally on port 27017.
  3. Launch the Spring Boot backend using Maven CLI:
    mvn spring-boot:run
    (Or press F5 in VS Code to load the local configurations automatically)

2. Frontend Local Setup

  1. Create a .env file in the frontend/ directory:
    VITE_API_BASE_URL=http://localhost:8081/api
  2. Navigate to the frontend/ folder, install dependencies, and start the development server:
    cd frontend
    npm install
    npm run dev
  3. Open http://localhost:5173 in your browser.

3. Swagger & Automated Tests

  • Swagger API Docs: Navigate to http://localhost:8081/swagger-ui/index.html (when backend is running).
  • Run Backend Tests: mvn clean test (16 controller mock MVC integration tests executed).
  • Verify Frontend Bundle: npm run build inside the frontend/ directory.

9. Production Deployment Setup

1. MongoDB Atlas Setup

  1. Create a free M0 cluster on MongoDB Atlas.
  2. In Database Access, create a user (e.g. bingumallagreeshmitha_db_user) with read/write access.
  3. In Network Access, add IP 0.0.0.0/0 (Allow Access from Anywhere) to permit Render server bindings.
  4. Copy your connection string from the Connect -> Drivers popup, URL-encode any special characters in your password (e.g. @ as %40), and set it as your MONGODB_URI environment variable.

2. Backend Render Deployment

  1. Create a new Web Service on Render, and link your GitHub repository.
  2. Select runtime Docker (Render will build the application using the root Dockerfile).
  3. Under Advanced, configure:
    • Health Check Path: /api/health
    • Environment Variables:
      • MONGODB_URI = mongodb+srv://<username>:<password>@cluster0.mongodb.net/?appName=Cluster0
      • MONGODB_DATABASE = jobtrack
      • JWT_SECRET = (Generate a secure random key)
      • JWT_EXPIRATION = 86400000
      • FRONTEND_URL = https://<your-vercel-domain>.vercel.app
  4. Click Deploy Web Service and copy the live URL (e.g., https://jobtrack-backend.onrender.com).

3. Frontend Vercel Deployment

  1. Import your GitHub repository on Vercel.
  2. Set the Root Directory setting to the frontend directory.
  3. Add the following Environment Variable:
    • VITE_API_BASE_URL = https://<your-render-backend-url>.onrender.com/api
  4. Click Deploy. Vercel will compile the React bundle and deploy it. Since vercel.json rewrite settings are loaded, client routing is managed automatically.

10. Example API Flow

Step 1: Register User

  • POST /api/auth/register
  • Body:
    {
      "name": "Greeshmitha",
      "email": "greeshmitha@example.com",
      "password": "Password123"
    }
  • Response (201 Created):
    {
      "id": "64d0be036577312389ab4101",
      "name": "Greeshmitha",
      "email": "greeshmitha@example.com",
      "createdAt": "2026-08-15T22:30:00"
    }

Step 2: Log In

  • POST /api/auth/login
  • Body:
    {
      "email": "greeshmitha@example.com",
      "password": "Password123"
    }
  • Response (200 OK):
    {
      "token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI2NGQwYm...",
      "tokenType": "Bearer",
      "expiresIn": 86400000,
      "user": {
        "id": "64d0be036577312389ab4101",
        "name": "Greeshmitha",
        "email": "greeshmitha@example.com",
        "createdAt": "2026-08-15T22:30:00"
      }
    }

Step 3: Create Job Application (With Custom Stages)

  • POST /api/applications
  • Headers: Authorization: Bearer <token>
  • Body:
    {
      "company": "Google",
      "role": "Software Engineer",
      "location": "Bangalore",
      "source": "REFERRAL",
      "appliedDate": "2026-08-15",
      "jobUrl": "https://careers.google.com/jobs/123",
      "notes": "Referred by senior dev",
      "stages": [
        { "name": "Applied", "order": 1 },
        { "name": "Technical Assessment", "order": 2 },
        { "name": "System Design Interview", "order": 3 },
        { "name": "Offer", "order": 4 }
      ]
    }
  • Response (201 Created):
    {
      "id": "64d0c1026577312389ab4102",
      "company": "Google",
      "role": "Software Engineer",
      "location": "Bangalore",
      "source": "REFERRAL",
      "appliedDate": "2026-08-15",
      "applicationStatus": "ACTIVE",
      "currentStage": {
        "id": "stage-uuid-1",
        "name": "Applied",
        "type": "CUSTOM",
        "status": "CURRENT",
        "order": 1,
        "scheduledAt": null,
        "completedAt": null,
        "notes": null
      },
      "stages": [
        { "id": "stage-uuid-1", "name": "Applied", "status": "CURRENT", "order": 1 },
        { "id": "stage-uuid-2", "name": "Technical Assessment", "status": "PENDING", "order": 2 },
        { "id": "stage-uuid-3", "name": "System Design Interview", "status": "PENDING", "order": 3 },
        { "id": "stage-uuid-4", "name": "Offer", "status": "PENDING", "order": 4 }
      ],
      "jobUrl": "https://careers.google.com/jobs/123",
      "notes": "Referred by senior dev",
      "createdAt": "2026-08-15T22:31:00",
      "updatedAt": "2026-08-15T22:31:00"
    }

Step 4: Advance Stage (Skipping Technical Assessment)

  • PATCH /api/applications/64d0c1026577312389ab4102/stage
  • Headers: Authorization: Bearer <token>
  • Body:
    {
      "stageId": "stage-uuid-3"
    }
  • Response (200 OK):
    {
      "id": "64d0c1026577312389ab4102",
      "company": "Google",
      "role": "Software Engineer",
      "applicationStatus": "ACTIVE",
      "currentStage": {
        "id": "stage-uuid-3",
        "name": "System Design Interview",
        "status": "CURRENT",
        "order": 3
      },
      "stages": [
        { "id": "stage-uuid-1", "name": "Applied", "status": "COMPLETED", "completedAt": "2026-08-15T22:32:00", "order": 1 },
        { "id": "stage-uuid-2", "name": "Technical Assessment", "status": "SKIPPED", "order": 2 },
        { "id": "stage-uuid-3", "name": "System Design Interview", "status": "CURRENT", "order": 3 },
        { "id": "stage-uuid-4", "name": "Offer", "status": "PENDING", "order": 4 }
      ]
    }

Step 5: Filter Applications (Search Google Applications)

  • GET /api/applications?search=Google&status=ACTIVE
  • Headers: Authorization: Bearer <token>
  • Response (200 OK):
    {
      "content": [
        {
          "id": "64d0c1026577312389ab4102",
          "company": "Google",
          "role": "Software Engineer",
          "location": "Bangalore",
          "source": "REFERRAL",
          "appliedDate": "2026-08-15",
          "applicationStatus": "ACTIVE",
          "currentStage": {
            "id": "stage-uuid-3",
            "name": "System Design Interview",
            "status": "CURRENT",
            "order": 3
          }
        }
      ],
      "page": 0,
      "size": 10,
      "totalElements": 1,
      "totalPages": 1,
      "first": true,
      "last": true
    }

Step 6: View Statistics

  • GET /api/applications/stats
  • Headers: Authorization: Bearer <token>
  • Response (200 OK):
    {
      "totalApplications": 1,
      "activeApplications": 1,
      "rejectedApplications": 0,
      "withdrawnApplications": 0,
      "stageCounts": {
        "System Design Interview": 1
      },
      "interviewRate": 100.0,
      "offerRate": 0.0
    }

10. Future Enhancements

  • Audit logs: Track exact histories of application status changes and user modifications.
  • Calendar integration: Synchronize interview stage dates with external services (like Google Calendar).
  • Resume parsing: Enable users to attach resume files and automatically extract details to pre-populate application fields.

About

This repository is a spring boot application that tracks the job applications of a user

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages