JobPulseAI

JobPulse AI πŸš€

AI-Powered Resume-Driven Job Discovery, Live Vacancy Verification & Automated Career Alerts

JobPulse AI is an intelligent job search and matching platform that bridges the gap between candidates and legitimate career opportunities. Instead of relying on generic keyword searches, JobPulse AI parses uploaded resumes across diverse engineering and professional disciplines, constructs a structured candidate profile, discovers vacancies from verified job feeds, validates application link accessibility using an SSRF-guarded verification engine, and delivers personalized recommendations and daily email alerts.

Repository Destination: https://github.com/Pratikshaprabhakarbande/JobPulseAI.git Maintainer: @Pratikshaprabhakarbande


πŸ“Œ Table of Contents


πŸ’‘ Core Highlights & Principles


✨ Key Features

1. Universal Resume-Driven Profiling

2. Live Job Discovery

3. Live Vacancy Verification Engine

4. Structured 5-Factor Matching Engine

5. Automated Scheduler & Email Alerts


πŸ”„ How It Works

1. RESUME UPLOAD      -> Upload PDF or DOCX file (magic-byte validated).
2. PROFILE PARSING    -> Extracts degree, skills, certifications, and documented projects.
3. PROFILE EDITOR     -> User reviews and adjusts target roles, skills, and locations.
4. JOB DISCOVERY      -> Ingests vacancies from Adzuna (India), Remotive (Remote) & Arbeitnow.
5. SSRF VERIFICATION  -> Safely resolves and audits application URLs against ATS platforms.
6. 5-FACTOR MATCHING  -> Evaluates job family, skills, experience, degree, and location fit.
7. LIVE DASHBOARD     -> Presents verified jobs with match breakdowns and filter controls.
8. DAILY DIGEST       -> node-cron dispatches deduplicated email alerts for top verified roles.

πŸ—οΈ System Architecture

flowchart TB
    subgraph Client["Frontend Client (React 19 + TypeScript + Vite)"]
        Dashboard["Dashboard View"]
        JobsFeed["Live Jobs Feed"]
        ProfileEditor["Candidate Profile Editor"]
        SettingsPage["Settings & Automation"]
        APIClient["API Client (`src/api.ts`)"]

        Dashboard --> APIClient
        JobsFeed --> APIClient
        ProfileEditor --> APIClient
        SettingsPage --> APIClient
    end

    subgraph Server["Backend Application (Express + TypeScript)"]
        SecHeaders["Security Headers (`nosniff`, `DENY`)"]
        RateLimits["Rate Limiters (Upload / Refresh / Email)"]

        subgraph Routes["API Routes"]
            R_Resume["`/api/resume`"]
            R_Jobs["`/api/jobs`"]
            R_Dash["`/api/dashboard/stats`"]
            R_Settings["`/api/settings`"]
            R_Sched["`/api/scheduler`"]
            R_Health["`/api/health`"]
        end

        subgraph CoreServices["Services Layer"]
            ResumeParser["Resume Analyzer (`resumeAnalyzer.ts`)"]
            JobEngine["Job Discovery Engine (`jobService.ts`)"]
            Verifier["Vacancy Verifier (`verificationService.ts`)"]
            Matcher["5-Factor Matcher (`aiService.ts`)"]
            Store["Local JSON DataStore (`dataStore.ts`)"]
            Scheduler["Automation Scheduler (`schedulerService.ts`)"]
            Emailer["Email Dispatcher (`emailService.ts`)"]
        end

        SecHeaders --> RateLimits --> Routes
        R_Resume --> ResumeParser --> Store
        R_Jobs --> JobEngine --> Verifier --> Matcher --> Store
        R_Dash --> Store
        R_Settings --> Store
        R_Sched --> Scheduler
        Scheduler --> JobEngine
        Scheduler --> Matcher
        Scheduler --> Emailer
    end

    subgraph External["External APIs & Services"]
        Adzuna["Adzuna API (India)"]
        Remotive["Remotive API (Remote)"]
        Arbeitnow["Arbeitnow API (Public Board)"]
        TargetATS["Employer ATS Systems"]
        SMTP["Gmail SMTP / Nodemailer"]
    end

    JobEngine --> Adzuna
    JobEngine --> Remotive
    JobEngine --> Arbeitnow
    Verifier --> TargetATS
    Emailer --> SMTP

For an in-depth design specification and data flow diagrams, see docs/ARCHITECTURE.md.


πŸ› οΈ Technology Stack

Layer Technology Purpose
Frontend Framework React 19 (^19.3.0) Declarative, component-driven user interface
Frontend Language TypeScript (~6.0.2) Strict client-side type safety
Bundler & Build Tool Vite (^8.3.0) High-speed HMR development server and production bundler
Styling & Effects Tailwind CSS v4 (^4.3.3) Modern CSS design with glassmorphic cards and responsive layouts
Icons Lucide React (^1.52.0) Clean, accessible vector UI icons
Backend Runtime Node.js (v18+ / v20+ / v24+) Server-side JavaScript execution environment
Backend Framework Express (^4.21.0) REST API routing and middleware pipeline
Backend Language TypeScript (^5.6.2) Strict server-side type safety
Execution Engine tsx (^4.19.1) Zero-compile TypeScript execution for development and tests
Document Parsing pdf-parse (^1.1.1), mammoth (^1.8.0) Stream-based text extraction for PDF and DOCX files
File Handling multer (^1.4.5-lts.1) Multipart form handling with in-memory validation
Job Discovery APIs Adzuna API, Remotive API, Arbeitnow API Live job feeds with authentic publication metadata
Job Verification Built-in Node.js dns & fetch SSRF-guarded HTTP destination and ATS validation engine
Scheduler node-cron (^4.6.0) Background automated discovery and digest daemon (09:00 IST)
Email Service nodemailer (^6.9.15) Responsive HTML email digest generation via SMTP
Database / Store JSON File Store (dataStore.ts) Persistent local candidate, settings, and job store in ./data/ with in-memory caching

πŸ“ Repository Structure

JobPulseAI/
β”œβ”€β”€ .github/workflows/          # GitHub Actions workflows
β”‚   β”œβ”€β”€ ci.yml                  # Automated test & Vite build pipeline
β”‚   └── deploy.yml              # GitHub Pages deployment workflow (client/dist)
β”œβ”€β”€ .env.example                # Root environment template with safe placeholders
β”œβ”€β”€ .gitignore                  # Git ignore rules (node_modules, .env, uploads, logs)
β”œβ”€β”€ CONTRIBUTING.md             # Contribution guidelines & security disclosure
β”œβ”€β”€ package.json                # Root workspace convenience scripts (install, dev, test, build)
β”œβ”€β”€ README.md                   # Main project documentation
β”œβ”€β”€ docs/                       # Technical documentation
β”‚   β”œβ”€β”€ API.md                  # Complete REST API reference
β”‚   └── ARCHITECTURE.md         # Architecture diagrams & component deep dive
β”œβ”€β”€ client/                     # Frontend Single Page Application
β”‚   β”œβ”€β”€ index.html              # HTML entry point with modern typography
β”‚   β”œβ”€β”€ package.json            # Client dependencies & scripts
β”‚   β”œβ”€β”€ tsconfig.json           # TypeScript configuration
β”‚   β”œβ”€β”€ vite.config.ts          # Vite build config with /api reverse proxy
β”‚   └── src/
β”‚       β”œβ”€β”€ main.tsx            # React application mount
β”‚       β”œβ”€β”€ App.tsx             # Main application UI, routing, and view components
β”‚       β”œβ”€β”€ api.ts              # Typed API client functions
β”‚       β”œβ”€β”€ index.css           # Tailwind CSS imports and theme tokens
β”‚       └── vite-env.d.ts       # Vite client environment typings
└── server/                     # Backend Express Application
    β”œβ”€β”€ package.json            # Server dependencies & scripts
    β”œβ”€β”€ tsconfig.json           # TypeScript server configuration
    β”œβ”€β”€ .env.example            # Backend-specific environment template
    └── src/
        β”œβ”€β”€ index.ts            # Server entry point, middleware & port listener
        β”œβ”€β”€ config/
        β”‚   └── index.ts        # Typed configuration loader & validation
        β”œβ”€β”€ middleware/
        β”‚   β”œβ”€β”€ errorHandler.ts # Global error & 404 response handlers
        β”‚   └── rateLimiter.ts  # In-memory IP rate limiters
        β”œβ”€β”€ routes/
        β”‚   β”œβ”€β”€ dashboard.ts    # /api/dashboard metrics endpoint
        β”‚   β”œβ”€β”€ jobs.ts         # /api/jobs listing, filtering & verification
        β”‚   β”œβ”€β”€ resume.ts       # /api/resume upload & candidate profile editor
        β”‚   β”œβ”€β”€ scheduler.ts    # /api/scheduler trigger & status controls
        β”‚   └── settings.ts     # /api/settings preferences & test email
        β”œβ”€β”€ services/
        β”‚   β”œβ”€β”€ aiService.ts    # 5-factor scoring & eligibility engine
        β”‚   β”œβ”€β”€ dataStore.ts    # In-memory & JSON persistence store
        β”‚   β”œβ”€β”€ emailService.ts # Nodemailer HTML digest generator
        β”‚   β”œβ”€β”€ jobService.ts   # Adzuna, Remotive, and Arbeitnow connectors
        β”‚   β”œβ”€β”€ resumeAnalyzer.ts# Universal multidisciplinary resume parser
        β”‚   β”œβ”€β”€ schedulerService.ts# node-cron daily automation service
        β”‚   └── verificationService.ts# SSRF-guarded link verification engine
        β”œβ”€β”€ tests/
        β”‚   β”œβ”€β”€ automatedTests.ts# 10 integration & unit test suites
        β”‚   └── runAllTests.ts  # Automated test runner script
        └── utils/
            └── types.ts        # Core TypeScript domain models & interfaces

βš™οΈ Prerequisites

Before running JobPulse AI locally, ensure you have the following installed:


πŸš€ Installation & Local Setup

Open Windows PowerShell and follow these copyable steps:

1. Clone the Repository

git clone https://github.com/Pratikshaprabhakarbande/JobPulseAI.git
cd JobPulseAI

2. Configure Backend Environment

cd server
Copy-Item .env.example .env

Open server/.env in your code editor and configure your preferences (see the Environment Configuration table below).

3. Install Dependencies

You can install dependencies across the entire workspace in one command, or per directory:

Option A β€” Workspace Root (Convenience Script):

# From the JobPulseAI root directory:
npm run install:all

Option B β€” Per Directory:

# Install backend dependencies
cd server
npm install

# Install frontend dependencies
cd ../client
npm install

4. Start the Application

Open two separate PowerShell terminal windows:

Terminal 1 β€” Backend Server:

cd server
npm run dev

(Or from root: npm run dev:server) The backend server will start at http://localhost:5000.

Terminal 2 β€” Frontend Client:

cd client
npm run dev

(Or from root: npm run dev:client) The Vite development server will start at http://localhost:5173.

Open your browser and navigate to http://localhost:5173.


πŸ” Environment Configuration

All backend settings are controlled through server/.env. Below is a comprehensive table of all supported variables:

Variable Name Purpose Required / Optional Safe Example / Placeholder Default Value
PORT Backend HTTP server port Optional 5000 5000
CORS_ORIGIN Allowed client origin for CORS Optional http://localhost:5173 http://localhost:5173
DATA_DIR Directory path for local JSON store Optional ./data ./data
ADZUNA_APP_ID Adzuna Job Board API Application ID Optional your_adzuna_app_id ""
ADZUNA_APP_KEY Adzuna Job Board API Secret Key Optional your_adzuna_app_key ""
ADZUNA_COUNTRY Adzuna target country code Optional in in
JOB_PROVIDER Preferred primary provider Optional adzuna or arbeitnow adzuna (if keys set) or arbeitnow
DEMO_MODE Load 10 synthetic test jobs for evaluation Optional false or true false (live feeds only)
AI_PROVIDER Candidate matching engine type Optional demo, gemini, or openai demo (built-in 5-factor scoring)
AI_API_KEY External AI API Key (if using Gemini/OpenAI) Optional your_ai_key ""
AI_MODEL External AI Model identifier Optional gpt-4o-mini gpt-4o-mini
EMAIL_HOST SMTP server hostname Optional smtp.gmail.com smtp.gmail.com
EMAIL_PORT SMTP port Optional 587 587
EMAIL_SECURE Use SSL for SMTP Optional false false
EMAIL_USER SMTP username / sender email Optional user@gmail.com ""
EMAIL_PASS SMTP 16-character App Password Optional xxxx xxxx xxxx xxxx ""
EMAIL_FROM Display sender email Optional JobPulse AI <user@gmail.com> ""
EMAIL_TO Default notification recipient Optional candidate@example.com ""
SCHEDULER_ENABLED Enable daily background discovery Optional true true
SCHEDULER_DAILY_TIME 24-hour time for daily run (IST) Optional 09:00 09:00
SCHEDULER_TIMEZONE Timezone identifier for cron Optional Asia/Kolkata Asia/Kolkata

[!TIP] Gmail SMTP Setup: To enable email alerts via Gmail, enable 2-Step Verification in your Google Account, visit Google App Passwords, create an app named β€œJobPulse AI”, and paste the generated 16-character code into EMAIL_PASS. Email alerts require EMAIL_USER, EMAIL_PASS, and EMAIL_TO to be configured, and email alerts must be enabled in Settings.


πŸ“± How to Use the Application

  1. Upload Resume:
    • Navigate to the Resume & Profile tab.
    • Drag and drop your PDF or DOCX resume into the upload box.
    • The universal analyzer extracts your education, technical skills, certifications, and documented projects.
  2. Review & Edit Candidate Profile:
    • In the Structured Candidate Profile section, review your extracted degree, skills, and target roles.
    • Add or remove target roles (e.g., Cybersecurity Intern, Junior SOC Analyst, Software Engineer Intern).
    • Click Save Candidate Profile & Recalculate to instantly refresh job recommendations.
  3. Explore Job Listings:
    • Navigate to the Jobs tab.
    • Review match scores, verification badges (Verified Active, Accessible), and India location pills.
    • Filter by Work Mode (Remote, Hybrid, On-site), Strict Recency (Last 24 Hours, 3 Days, 7 Days), or Verified Open Only.
  4. On-Demand Link Verification:
    • Click on any job card to open the Job Details view.
    • In the Live Vacancy Verification card, click Check Live Status to execute an SSRF-guarded HTTP audit of the destination application link.
  5. Run Automation & Email Alerts:
    • Go to the Dashboard or Settings tab.
    • Click ⚑ Run Full Automation Now to trigger an immediate discovery, verification, and email dispatch cycle.
    • Alternatively, click Send Test Email Digest in Settings to test email delivery.

βš–οΈ Honest Verification & Matching Limitations

JobPulse AI operates on principles of transparency and evidence-based reporting. Users and reviewers should note:

  1. Relevance Estimation vs. Hiring Guarantee: Match scores represent an algorithmic evaluation of profile relevance against listed vacancy requirements. A 90% score does not guarantee employment or an interview.
  2. Vacancy Volatility: External employer requisitions change frequently. Companies may pause hiring or close an opening without immediately removing their public careers page.
  3. Accessible Links Do Not Guarantee an Open Vacancy (HTTP 200 Ambiguity): A reachable URL returning HTTP 200 does not prove that a requisition is actively accepting applications. Career sites often return HTTP 200 for expired listings, generic career landing pages, or login forms. These are categorized as LIKELY_OPEN and never falsely labeled as conclusively verified unless confirmed on an official ATS domain or with explicit application call-to-action elements.
  4. Strict Recency Window Exclusion: The application enforces honest publication dates. Vacancies without a reliable publication timestamp from the source feed are tagged postedDateSource: 'unverified' and are explicitly excluded from strict 24-hour and 72-hour filters. They appear only when the filter is widened to 7 days or 14 days (maxAge > 72).
  5. Anti-Bot & Cloudflare Protections: Certain employer portals return HTTP 403/429 or present CAPTCHAs to automated requests, or exceed the 6-second verification timeout. JobPulse AI labels these listings as VERIFICATION_BLOCKED rather than guessing their status.
  6. Local Host & Scheduler Dependency: Background automation via node-cron runs in-process inside the Express backend server. The backend process and host machine must remain running for scheduled daily runs to trigger. Deduplication tracks the last 100 notified IDs in settings.json to prevent repeated alerts during scheduled runs.
  7. Local JSON File Persistence: Data is stored locally as structured JSON documents in ./data/ (jobs.json, matches.json, profile.json, resume.json, settings.json, scheduler_status.json) with an in-memory cache. It does not use a distributed cloud database, making it ideal for desktop or single-server deployment.

πŸ“‘ REST API Reference

For detailed request and response payloads, see docs/API.md.

Method Endpoint Purpose Required Inputs
GET /api/health Health check & active provider status None
GET /api/dashboard/stats Aggregated metrics, profile status, and scheduler state None
POST /api/resume/upload Upload & parse resume document multipart/form-data with resume file
GET /api/resume Retrieve current resume file metadata None
GET /api/resume/profile Retrieve structured candidate profile None
PUT /api/resume/profile Edit candidate profile preferences & recalculate matches JSON body with profile updates
DELETE /api/resume Remove resume and candidate profile None
GET /api/jobs Retrieve vacancies with filter and sort controls Optional query parameters (search, maxAge, verifiedOnly, etc.)
GET /api/jobs/:id Retrieve specific job details & analysis Job ID in path
POST /api/jobs/:id/verify Execute on-demand live link verification Job ID in path
POST /api/jobs/:id/analyze Evaluate a single job against candidate profile Job ID in path
POST /api/jobs/analyze-all Evaluate all loaded jobs against candidate profile None
POST /api/jobs/refresh Ingest fresh vacancies from configured providers None
GET /api/settings Retrieve user alert & email settings None
PUT /api/settings Update alert preferences JSON body with settings updates
POST /api/settings/email/test Send test job digest email Optional JSON body { email: string }
GET /api/scheduler/status Check background cron scheduler state None
POST /api/scheduler/trigger Manually trigger full background automation cycle None
POST /api/scheduler/start Start or resume cron scheduler None
POST /api/scheduler/stop Pause cron scheduler None

πŸ§ͺ Testing & Quality Assurance

JobPulse AI includes an automated unit and integration test suite covering resume parsing, multi-domain mapping, location restrictions, experience barriers, closed-vacancy handling, SSRF guards, and recency filters.

Running Backend Tests

cd server
npm test

Verified Test Output:

═══════════════════════════════════════════════════════
   JOBPULSE AI β€” AUTOMATED QA & INTEGRATION SUITE
═══════════════════════════════════════════════════════

  βœ… PASS: Resume Parser: Multi-domain mapping (Cybersecurity, EEE, Civil)
  βœ… PASS: Matching: Relevant Bengaluru Cybersecurity Internship matches Cyber profile
  βœ… PASS: Matching: Hardware / Embedded Intern matches EEE resume
  βœ… PASS: Matching: Site Engineer Trainee matches Civil resume
  βœ… PASS: Matching: Unrelated parcel delivery vacancy penalized heavily
  βœ… PASS: Location: Germany onsite job flagged when candidate prefers India
  βœ… PASS: Experience Barrier: Senior 5+ years role penalized for fresher candidate
  βœ… PASS: Verification: Closed vacancy produces score of 0 and is marked ineligible
  βœ… PASS: Security SSRF Guard: Blocks localhost, internal IPs and cloud metadata
  βœ… PASS: Recency Filter: Distinguishes genuine 24h publication timestamps from old/unverified

───────────────────────────────────────────────────────
  Total: 10 | Passed: 10 | Failed: 0
═══════════════════════════════════════════════════════

Running Frontend Production Build & TypeScript Check

cd client
npm run build

Successfully transforms all modules, completes TypeScript compilation, and bundles production assets with exit code 0.


πŸ›‘οΈ Security & Privacy Hardening

JobPulse AI implements defense-in-depth security measures across both frontend and backend:

  1. SSRF Protection (verificationService.ts):
    • Performs strict DNS resolution checks prior to executing HTTP requests.
    • Prohibits loopback (127.0.0.1, ::1), private RFC1918 subnets (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), link-local IPs (169.254.0.0/16), and cloud instance metadata endpoints (169.254.169.254, metadata.google.internal).
  2. Binary Magic-Byte Inspection (resume.ts):
    • Rejects spoofed files disguised with .pdf or .docx extensions by validating file header signatures.
  3. Path Traversal Defense:
    • Sanitizes uploaded filenames using path.basename() and regex filters, storing files in isolated directories.
  4. Immediate File Cleanup:
    • Temporary upload files are deleted immediately after text extraction.
  5. Security Headers (index.ts):
    • Injects X-Content-Type-Options: nosniff, X-Frame-Options: DENY, and Referrer-Policy: strict-origin-when-cross-origin.
  6. Rate Limiting (rateLimiter.ts):
    • In-memory IP rate limiters restrict resume uploads (10 per 15 min), job refreshes (10 per 15 min), and test emails (5 per 15 min).
  7. Secret Isolation:
    • Real API credentials and SMTP passwords reside strictly in .env and are never exposed to the frontend or checked into version control.

πŸ”§ Troubleshooting Guide

1. Port 5000 or 5173 Already in Use

2. β€œReal job source not configured” Banner

3. Email Alerts Fail to Deliver

4. Resume Text Extraction Warning


πŸ—ΊοΈ Future Roadmap

Planned enhancements for future releases include:


🀝 Contributing & License

Contributing

Contributions, bug reports, and suggestions are welcome! Please review CONTRIBUTING.md for branch naming conventions, development guidelines, and pull request procedures.

To report bugs or request features, open a GitHub Issue.

License

No explicit license has been declared yet. An appropriate open-source license (such as MIT or Apache-2.0) should be selected prior to public redistribution.


Developed with precision for authentic career discovery by @Pratikshaprabhakarbande.