Skip to content

Arjun20X/AI_Inovation

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

16 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🧠 AI Skill Gap Learning Platform

"Turn your resume into a roadmap."

An intelligent, full-stack platform that analyzes your resume or skills against any job title, identifies your exact skill gaps using NLP, and generates a personalized AI-powered learning roadmap to close them.

Live Demo Node.js React Python MongoDB Gemini AI


🌐 Live Demo

https://aiskillgap.netlify.app/


πŸ“Œ Project Overview

Project Name AI Skill Gap Learning Platform
Impact Eliminates guesswork from career transitions β€” tells you exactly what to learn and where to learn it.
Description A three-tier web application where users upload their resume (PDF/DOCX) or paste raw text, select a target job role, and receive: (1) a list of skills they already have, (2) skills they are missing, and (3) a curated, AI-generated 5-step learning roadmap with free resources β€” all in seconds.

✨ Key Features

Feature Description
πŸ“„ Resume Parsing Accepts PDF, DOCX, or plain text input
πŸ” NLP Skill Extraction Uses spaCy PhraseMatcher to detect 30+ technical skills from resume content
πŸ€– Dynamic Job Analysis Gemini 2.5 Flash dynamically determines the top 10–15 skills required for any job title
πŸ—ΊοΈ AI Roadmap Generation Produces a personalized, structured 5-step learning plan with free resource links
πŸ“Š Visual Dashboard D3.js-powered charts visualizing skill gap breakdown
πŸ” JWT Authentication Secure user registration and login with token-based protected routes
πŸ›‘οΈ Protected Routes Frontend and backend both enforce authentication barriers
πŸ“± Responsive UI Fully responsive design built with Tailwind CSS
⚑ Toast Notifications Real-time feedback using Sonner toast system

πŸ—οΈ System Architecture

The application follows a three-tier microservices-inspired architecture:

graph TB
    subgraph CLIENT["πŸ–₯️ Client (React + Vite)"]
        UI["Pages: Login, Register,\nProfileInput, Dashboard"]
        CTX["AuthContext\n(JWT State)"]
        UI --> CTX
    end

    subgraph SERVER["βš™οΈ Server (Node.js + Express)"]
        AUTH_R["/api/auth\nregister | login"]
        SKILL_R["/api/skills/analyze\n(Protected)"]
        AUTH_MW["authMiddleware\n(JWT Verify)"]
        GEMINI["Google Gemini 2.5 Flash\n(Dynamic Skills + Roadmap)"]
        SKILL_R --> AUTH_MW --> GEMINI
    end

    subgraph AI["πŸ€– AI Microservice (Python + Flask)"]
        SPACY["spaCy NLP\n(Skill Extraction)"]
        PARSER["PyPDF2 / python-docx\n(File Parsing)"]
        PARSER --> SPACY
    end

    subgraph DB["πŸ—„οΈ MongoDB Atlas"]
        USERS["Users Collection\n(name, email, hashed_password)"]
    end

    UI -->|"HTTP Requests\n(Axios)"| AUTH_R
    UI -->|"multipart/JSON"| SKILL_R
    SKILL_R -->|"Base64 file\nor text JSON"| SPACY
    AUTH_R -->|"Mongoose ODM"| USERS
    GEMINI -->|"Structured JSON\nResponse"| SKILL_R
    SKILL_R -->|"Gap Report +\nRoadmap JSON"| UI
Loading

πŸ”„ Application Flow Diagram

flowchart TD
    A([User Opens App]) --> B{Authenticated?}
    B -- No --> C[Login / Register Page]
    C -->|Submit credentials| D[POST /api/auth/login or /register]
    D -->|Success: JWT Token| E[Store Token in AuthContext]
    E --> F[ProfileInput Page]
    B -- Yes --> F

    F --> G[User enters Target Job Title]
    G --> H{Input Method?}
    H -- Text --> I[Paste resume text]
    H -- File --> J[Upload PDF or DOCX]

    I --> K[POST /api/skills/analyze]
    J --> K

    K --> L[authMiddleware verifies JWT]
    L --> M[Express sends payload to Python /extract_skills]
    M --> N[spaCy NLP extracts user skills]
    N --> O[Return extracted skills to Express]

    O --> P[Express calls Gemini API\nfor dynamic required skills]
    P --> Q[Calculate Skill Gap\nmissing = required - user skills]
    Q --> R[Express calls Gemini API\nfor Learning Roadmap]
    R --> S[Return full analysis JSON to React]

    S --> T[Dashboard Page]
    T --> U[D3.js Skill Gap Chart]
    T --> V[5-Step Roadmap Cards]
    T --> W[Skill Lists: βœ… Have / ❌ Missing]
Loading

πŸ” Auth / Login Flow

sequenceDiagram
    participant User
    participant React Client
    participant Express Server
    participant MongoDB

    User->>React Client: Submit Register/Login Form
    React Client->>Express Server: POST /api/auth/register (or /login)
    Express Server->>MongoDB: findOne({ email })

    alt Registration
        MongoDB-->>Express Server: User not found
        Express Server->>MongoDB: User.create({ name, email, password })
        Note over Express Server,MongoDB: Pre-save hook: bcrypt.hash(password, 10)
        MongoDB-->>Express Server: User document saved
    else Login
        MongoDB-->>Express Server: User document found
        Express Server->>Express Server: bcrypt.compare(enteredPassword, hash)
    end

    Express Server->>Express Server: jwt.sign({ id }, JWT_SECRET, { expiresIn: '30d' })
    Express Server-->>React Client: { _id, name, email, token }
    React Client->>React Client: Store token in AuthContext state
    React Client->>User: Redirect to /ProfileInput (protected route)
Loading

πŸ“Š Database Schema

erDiagram
    USERS {
        ObjectId _id PK
        String name "required"
        String email "required, unique"
        String password "required, bcrypt hashed"
        Date createdAt "auto-generated"
        Date updatedAt "auto-generated"
    }
Loading

Note: The application is currently stateless for analysis results β€” skill gap reports are computed on-the-fly and returned to the client without being persisted, keeping the database lean.


πŸ” Request Lifecycle

sequenceDiagram
    participant Client as React Client
    participant Express as Express Server
    participant Auth as authMiddleware
    participant Python as Flask AI Service
    participant Gemini as Google Gemini API

    Client->>Express: POST /api/skills/analyze<br/>(Authorization: Bearer JWT)
    Express->>Auth: Verify JWT Token
    Auth->>Auth: jwt.verify(token, JWT_SECRET)
    Auth->>Express: req.user = { _id, name, email }

    Express->>Python: POST /extract_skills<br/>{ fileBuffer | resumeText, targetRole }
    Python->>Python: base64 decode β†’ PyPDF2/python-docx parse
    Python->>Python: spaCy PhraseMatcher β†’ extract skills
    Python-->>Express: { skills: ["React", "Git", ...] }

    Express->>Gemini: Dynamic skills for targetJobTitle
    Gemini-->>Express: { requiredSkills: ["TypeScript", "Docker", ...] }

    Express->>Express: calculateMissingSkills(required, userSkills)
    Express->>Gemini: Generate 5-step roadmap for missingSkills
    Gemini-->>Express: { summary, steps[{skill,goal,resourceURL}], conclusion }

    Express-->>Client: Full JSON response:<br/>{ requiredSkills, userSkills, missingSkills, learningRoadmap }
    Client->>Client: Render Dashboard with D3 Chart + Roadmap Cards
Loading

πŸ› οΈ Tech Stack

Frontend β€” Client/

Technology Version Purpose
React 19 UI Component Framework
Vite 7 Build Tool & Dev Server
React Router DOM 7 Client-side Routing
Tailwind CSS 3 Utility-First Styling
D3.js 7 Data Visualization Charts
Axios 1 HTTP Client
Sonner 2 Toast Notification System
Lucide React latest Icon Library

Backend β€” Server/

Technology Version Purpose
Node.js 18+ JavaScript Runtime
Express 5 Web Framework
Mongoose 8 MongoDB ODM
JSON Web Token 9 Authentication Tokens
bcryptjs 3 Password Hashing
@google/genai 1 Google Gemini AI SDK
Axios 1 HTTP calls to AI Microservice
express-async-handler 1 Async Error Wrapper
dotenv 17 Environment Variables

AI Microservice β€” AI_service/

Technology Version Purpose
Python 3.10+ Runtime
Flask latest Micro Web Framework
Flask-RESTful latest REST API Resource Structure
Flask-CORS latest Cross-Origin Support
spaCy latest NLP Skill Extraction
en_core_web_sm β€” spaCy English Language Model
PyPDF2 latest PDF Text Extraction
python-docx latest DOCX Text Extraction

Infrastructure

Service Role
MongoDB Atlas Cloud NoSQL Database
Google Gemini 2.5 Flash AI-powered skill and roadmap generation
Vercel / Netlify Frontend hosting
Railway / Render Backend & AI service hosting

πŸ“ Folder Structure

AI_Inovation/
β”‚
β”œβ”€β”€ πŸ“ Client/                    # React + Vite Frontend
β”‚   β”œβ”€β”€ public/
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ assets/               # Static images and media
β”‚   β”‚   β”œβ”€β”€ components/           # Reusable UI components
β”‚   β”‚   β”œβ”€β”€ context/
β”‚   β”‚   β”‚   └── AuthContext.jsx   # JWT auth state (React Context)
β”‚   β”‚   β”œβ”€β”€ lib/                  # Utility / helper functions
β”‚   β”‚   β”œβ”€β”€ pages/
β”‚   β”‚   β”‚   β”œβ”€β”€ LoginPage.jsx     # User login UI
β”‚   β”‚   β”‚   β”œβ”€β”€ RegisterPage.jsx  # User registration UI
β”‚   β”‚   β”‚   β”œβ”€β”€ ProfileInput.jsx  # Resume / text input + job title
β”‚   β”‚   β”‚   β”œβ”€β”€ DashboardPage.jsx # Skill gap results + roadmap
β”‚   β”‚   β”‚   β”œβ”€β”€ Home.jsx          # Landing page
β”‚   β”‚   β”‚   └── NotFoundPage.jsx  # 404 fallback
β”‚   β”‚   β”œβ”€β”€ utils/                # Axios instance / API helpers
β”‚   β”‚   β”œβ”€β”€ App.jsx               # Router with protected routes
β”‚   β”‚   └── main.jsx              # React entry point
β”‚   β”œβ”€β”€ index.html
β”‚   β”œβ”€β”€ vite.config.js
β”‚   └── tailwind.config.js
β”‚
β”œβ”€β”€ πŸ“ Server/                    # Node.js + Express Backend
β”‚   β”œβ”€β”€ config/
β”‚   β”‚   └── db.js                 # MongoDB connection via Mongoose
β”‚   β”œβ”€β”€ controllers/
β”‚   β”‚   β”œβ”€β”€ auth.js               # registerUser, loginUser
β”‚   β”‚   └── skillController.js    # analyzeUserText (main orchestrator)
β”‚   β”œβ”€β”€ middleware/
β”‚   β”‚   β”œβ”€β”€ authMiddleware.js     # JWT protect middleware
β”‚   β”‚   └── errorMiddleware.js    # Global error handler
β”‚   β”œβ”€β”€ models/
β”‚   β”‚   └── User.js               # Mongoose User schema
β”‚   β”œβ”€β”€ routes/
β”‚   β”‚   β”œβ”€β”€ authRoutes.js         # POST /api/auth/register|login
β”‚   β”‚   └── skillRoutes.js        # POST /api/skills/analyze (protected)
β”‚   β”œβ”€β”€ server.js                 # Express app entry point
β”‚   └── .env                      # Environment variables (gitignored)
β”‚
β”œβ”€β”€ πŸ“ AI_service/                # Python + Flask Microservice
β”‚   β”œβ”€β”€ app.py                    # Flask app with /extract_skills endpoint
β”‚   β”œβ”€β”€ requirements.txt          # Python dependencies
β”‚   └── venv/                     # Python virtual environment
β”‚
β”œβ”€β”€ package.json                  # Root-level scripts
└── README.md

βš™οΈ Installation & Setup

Prerequisites

  • Node.js v18+
  • Python 3.10+
  • MongoDB Atlas account (free tier works)
  • Google AI Studio API key (for Gemini)

1. Clone the Repository

git clone https://github.com/your-username/AI_Inovation.git
cd AI_Inovation

2. Backend Setup (Server/)

cd Server
npm install

Create Server/.env:

PORT=5000
MONGO_URI=mongodb+srv://<user>:<password>@cluster0.mongodb.net/skillbridge
JWT_SECRET=your_super_secret_jwt_key_here
GOOGLE_API_KEY=your_google_gemini_api_key
PYTHON_SERVICE_URL=http://localhost:5001

Start the server:

npm run server   # Development (nodemon)
# or
npm start        # Production

3. AI Microservice Setup (AI_service/)

cd AI_service
python -m venv venv

# Windows
venv\Scripts\activate
# Linux/Mac
source venv/bin/activate

pip install -r requirements.txt
python -m spacy download en_core_web_sm

Start the Flask service:

python app.py
# Runs on http://localhost:5001

4. Frontend Setup (Client/)

cd Client
npm install

Create Client/.env:

VITE_API_URL=http://localhost:5000

Start the dev server:

npm run dev
# Runs on http://localhost:5173

5. All Services Running

Service Port Command
React Frontend 5173 npm run dev in Client/
Express Backend 5000 npm run server in Server/
Flask AI Service 5001 python app.py in AI_service/

πŸ”’ Security Practices

Practice Implementation
Password Hashing bcryptjs with salt rounds of 10 β€” passwords are never stored in plaintext
JWT Authentication Tokens signed with JWT_SECRET, expire in 30 days
Protected API Routes authMiddleware verifies every request to /api/skills/* before processing
Protected Frontend Routes ProtectedRoute component in React redirects unauthenticated users to /login
Environment Variables All secrets in .env files β€” never committed to Git (.gitignore enforced)
Request Size Limiting Express configured with 5mb body limit to prevent payload attacks
CORS Enabled at both Express and Flask levels with appropriate headers
Error Masking Global errorHandler middleware returns sanitized error messages β€” no stack traces to client
Input Validation Auth controller checks for missing/duplicate fields before any DB operation

πŸ“‘ API Documentation

Base URL

http://localhost:5000/api

πŸ” Auth Routes β€” /api/auth

POST /api/auth/register

Register a new user.

Request Body:

{
  "name": "Arjun Sharma",
  "email": "arjun@example.com",
  "password": "securepassword123"
}

Success Response 201:

{
  "_id": "64abc123...",
  "name": "Arjun Sharma",
  "email": "arjun@example.com",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Error Responses:

Status Message
400 User already exists
400 Invalid user data

POST /api/auth/login

Authenticate an existing user.

Request Body:

{
  "email": "arjun@example.com",
  "password": "securepassword123"
}

Success Response 200:

{
  "_id": "64abc123...",
  "name": "Arjun Sharma",
  "email": "arjun@example.com",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Error Responses:

Status Message
401 Invalid email or password

πŸ€– Skill Routes β€” /api/skills (Protected)

All routes require the header:

Authorization: Bearer <JWT_TOKEN>

POST /api/skills/analyze

Analyze resume content and return a full skill gap report and learning roadmap.

Request Body (Text Input):

{
  "resumeText": "Experienced developer with React, Node.js, MongoDB, and Git skills...",
  "targetJobTitle": "Full Stack Developer"
}

Request Body (File Input):

{
  "fileBuffer": "<base64_encoded_file_content>",
  "filename": "resume.pdf",
  "targetJobTitle": "Data Scientist"
}

Success Response 200:

{
  "message": "Full dynamic skill analysis and roadmap generated successfully.",
  "targetRole": "Data Scientist",
  "requiredSkills": ["Python", "Pandas", "NumPy", "SQL", "Scikit-learn", "Tableau", "Statistics"],
  "userSkills": ["Python", "SQL"],
  "missingSkills": ["Pandas", "NumPy", "Scikit-learn", "Tableau", "Statistics"],
  "learningRoadmap": {
    "summary": "You have a strong Python foundation...",
    "steps": [
      {
        "skill": "Pandas",
        "goal": "Master data manipulation and analysis",
        "resourceTitle": "Pandas Official Docs β€” 10 Minutes to Pandas",
        "resourceURL": "https://pandas.pydata.org/docs/user_guide/10min.html"
      }
    ],
    "conclusion": "With consistent effort over 3-4 months, you'll be ready!"
  },
  "userId": "64abc123..."
}

Error Responses:

Status Message
400 Target job title is missing
400 Request body is empty or missing required fields
401 Not authorized, token failed
500 AI skill extraction service is currently unavailable

🐍 AI Microservice β€” http://localhost:5001

POST /extract_skills

Internal endpoint called by Express. Not intended for public use.

Request Body:

{
  "resumeText": "Raw text content OR",
  "fileBuffer": "<base64>",
  "filename": "resume.pdf",
  "targetRole": "Full Stack Developer"
}

Success Response 200:

{
  "skills": ["React", "Node", "MongoDB", "Git"],
  "raw_text_length": 2048,
  "targetRole": "Full Stack Developer"
}

⚑ Performance & Optimizations

Area Optimization
File Transfer Files are encoded as Base64 in JSON between Express and Flask β€” eliminates multipart boundary parsing overhead
NLP Speed spaCy PhraseMatcher (not full NER) used for skill extraction β€” O(n) linear complexity, significantly faster than regex
AI API Efficiency Gemini gemini-2.5-flash selected for its speed/cost balance over Pro models
Structured AI Output responseSchema enforced in Gemini API calls β€” returns valid JSON directly, skipping post-processing
Body Size Limit Express body parser capped at 5mb to prevent large payload abuse
Async Error Handling express-async-handler wraps controllers β€” avoids repetitive try/catch boilerplate
Fallback Logic If Gemini skill-fetch fails, falls back to a hardcoded MERN skill list β€” prevents total failure
Model Loading spaCy model loaded once at startup, cached in memory β€” avoids reloading on every request
Frontend Build Vite + React β€” significantly faster HMR and smaller bundle than CRA

πŸš€ Deployment

Frontend β€” Vercel (Recommended)

  1. Push Client/ to GitHub
  2. Import into vercel.com
  3. Set root directory to Client
  4. Add environment variable: VITE_API_URL=https://your-backend.railway.app
  5. Deploy βœ…

Backend (Express) β€” Railway

  1. Push Server/ to GitHub
  2. Create a new project on railway.app
  3. Add all environment variables from .env
  4. Set start command: node server.js
  5. Deploy βœ…

AI Microservice (Flask) β€” Render

  1. Push AI_service/ to GitHub
  2. Create a new Web Service on render.com
  3. Set build command: pip install -r requirements.txt && python -m spacy download en_core_web_sm
  4. Set start command: python app.py
  5. Update PYTHON_SERVICE_URL in Railway to point to Render URL βœ…

Important: Set debug=False in app.py and ensure HOST=0.0.0.0 for all cloud deployments.


πŸ‘¨β€πŸ’» Author

Arjun

Full Stack Developer & AI Enthusiast

GitHub LinkedIn

Built with ❀️ using the MERN stack + Python AI microservices


⭐ If this project helped you, consider starring the repo!

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors