A professional-grade SaaS frontend productivity tool designed to help users track, monitor, and analyze their job search process. Built to fulfill a comprehensive Product Requirements Document (PRD), this application demonstrates advanced React architecture, complex state management, and an award-worthy dual-theme user interface.
Job seekers today apply to dozens or even hundreds of jobs across platforms such as LinkedIn, company career pages, referrals, and job boards. Managing this volume manually leads to critical failures:
- Forgetting application details and locations.
- Missing interview schedules and follow-ups.
- Lacking visibility into job search progress (e.g., Conversion rates).
- Having difficulty comparing offers or salary ranges geographically.
Most candidates rely on spreadsheets or physical notes, which lack automation, rapid filtering, visual analytics, and proper stage organization.
This project centralizes the job tracking experience into a highly responsive, visually stunning React dashboard. It simulates a real SaaS productivity tool by offering dynamic searches, rich dashboard metrics, status categorizations, and persistent data storage.
- University Students applying for campus placements.
- Professionals / Developers switching jobs or tracking curated leads.
- Freelancers monitoring multiple concurrent project inquiries.
The application fulfills 8 specific functional pillars mandated by the PRD:
A robust form engine built with react-hook-form and validated by yup.
- Fields Captured: Company Name, Job Role, Location, Salary Range, Platform, Status, Dates, and customized Markdown Notes.
- Validation Guards: Enforces rigid rules for required fields (Company, Role, Date).
A dynamic layout displaying all applications.
- Features semantic UI cards showing Company initialization logic, roles, and status badges.
- Integrated actions on every card: Edit, Delete (via customized Framer Motion warning modals), and Bookmark.
Users can search by Company Name or Role through a dedicated, isolated search engine.
- Component Extraction: Search logic is encapsulated in a standalone
SearchBarcomponent for better separation of concerns. - Search Performance: Implements a custom
useDebouncehook (500ms) to drastically reduce render cycles, ensuring filtering only happens after the user pauses typing.
- Filters: Isolates views by Status (Applied, Interviewing, Offer, Rejected), Platform, and Location Types.
- Sorting Engine: Sort applications dynamically by Applied Date, Salary (High/Low), or Alphabetically by Company Name.
Applications can be isolated using Pipeline Tabs directly in the UI, separating the noise of rejected roles from critical active interviews.
A dedicated analytics view acting as the control center.
- Key Metrics: Total applications, Interview rates, Offer conversion rates, and Maximum vs Average Salaries.
- Visual Data: Integrated
Rechartslibrary rendering Pie Charts (Application Stages) and Bar Charts (Monthly application cadence). - Mock API Integration: Seeds the environment with initial sample data fetched asynchronously from
https://dummyjson.com/productsusing Axios, transforming external brand/product data into job application contexts.
- π Cyber-Terminal Dark Mode: Custom data-heavy design featuring layered green depth.
- βοΈ Editorial Neo-Brutalism Light Mode: Highly contrasting borders and harsh shadows.
Dedicated Details page with Markdown support to render long-form external Job Descriptions beautifully.
This project was built to master modern React architecture. Here are the precise concepts utilized:
- What it means: Normally in React, to pass data from a parent component to a deeply nested child, you have to pass it through every component in between (called "Prop Drilling"). The Context API creates a "global broadcast" bubble.
- How it's used: We use
ApplicationContextto hold our grand array of job data and the current Theme setting. Now, theSidebarcan access the total application count, and theDashboardcan access the charts data, without passing props.
- What it means: Hooks are functions that let you "hook into" React state and lifecycle features. Custom hooks let you package complex logic into a single reusable function.
- How it's used:
useLocalStorageintercepts all calls to update our Reactapplicationsstate and automatically saves a duplicate stringified copy to the browser's persistentlocalStorage.useDebouncelimits how often a search query updates the UI, preventing lag while typing.
- What it means: Breaking a massive user interface into tiny, hyper-focused puzzle pieces that combine to make the whole.
- How it's used: Instead of putting 200 lines of chart code inside
Dashboard.jsx, we built<PipelineDonut />and<MonthlyBarChart />. This makes the Dashboard file clean and allows us to reuse the exact same Pie chart on theAnalytics.jsxpage.
- What it means: React Router swaps out components based on the URL in the browser bar.
- How it's used: We created a dynamic route:
/applications/:id. When the user clicks a job card, theJobDetailscomponent reads that:idfrom the URL using theuseParams()hook, looks up that specific job, and renders the data.
- What it means: React applications often need to pull data from external servers. This happens "asynchronously" so the screen doesn't freeze while waiting for the internet.
- How it's used: We use
Axioswithin anuseEffecthook to pull 12 sample products from the DummyJSON API. We then "map" this product data (Brand, Title, Price) into our Job Application format to seed the dashboard with realistic data on first load.
- What it means:
useCallbackcaches a function so it isn't wastefully recreated every time the screen updates. - How it's used: Wrapped our global search and form submission handlers to guarantee maximum React performance and avoid infinite rendering loops.
If you are learning React and want to understand how this application was constructed from scratch, here is the architectural sequence:
- Bootstrapped the application using Vite (
npm create vite@latest). - Installed
react-router-dom. - Created a basic layout (
App.jsx) with a static<Sidebar />on the left and a dynamic<main>area filling the remaining space using CSS Flexbox. - Mapped routes (
/dashboard,/applications,/analytics, etc.) to empty placeholder components.
- Created
ApplicationContext.jsxto hold the masterapplicationsarray. - Built the
useLocalStorage.jshook to ensure the array is read from and saved towindow.localStorageautomatically on every state change. - Created a robust API utility (
api.js) to format dates, parse currencies, and hold the initial seed logic.
- Constructed
index.cssstrictly using CSS Variables (Tokens). - Defined explicit variables for Backgrounds, Accents, text, and standard Borders.
- Added the
[data-theme="light"]wrapper in CSS to aggressively overwrite the variables purely via CSS, completely decoupled from Javascript logic.
- Forms: Created the
AddApplicationform utilizingreact-hook-form. - The Components: Built
JobCardto render individual entries, passing specific application data down as props. - The Data Views: Wired Recharts into
DashboardandAnalytics. Filtered the Context array using logic likeapplications.filter(a => a.status === 'Offer').length. - Dynamic Detail Page: Built the
JobDetails.jsxcomponent integratingreact-markdownto parse formatted job descriptions.
- Installed
framer-motionandreact-icons. - Wrapped the router in
AnimatePresencefor smooth page transitions. - Applied
motion.divwith spring mechanics to our customConfirmModalto make dangerous actions feel weighty and premium.
| Route | Component | Purpose |
|---|---|---|
/dashboard |
Dashboard.jsx |
High-level widgets, recent activity, tip-of-the-day. |
/applications |
Applications.jsx |
Master list featuring search, filter, and sort implementations. |
/applications/new |
AddApplication.jsx |
Reusable Form interface for creating entries. |
/applications/:id |
AddApplication.jsx |
Overloaded Form interface for editing existing entries. |
/applications/:id/details |
JobDetails.jsx |
Distraction-free reading view for Markdown job descriptions. |
/analytics |
Analytics.jsx |
Deep charts and KPI breakdowns. |
/bookmarks |
Bookmarks.jsx |
Filtered aggregate of all favored roles. |
The application utilizes the following strict JSON schema structure for every logged job:
{
"id": "GOOGLE-SWE-1",
"company": "Google",
"role": "Software Engineer",
"location": "Remote",
"salary": 140000,
"currency": "USD",
"platform": "LinkedIn",
"status": "Interviewing",
"appliedDate": "2026-03-15",
"interviewDate": "2026-03-30",
"notes": "**Focus heavily on System Design**\n- Need to review load balancing.",
"bookmarked": true
}| Package | Purpose in Project |
|---|---|
react-router-dom |
Handles all SPA view transitions and URL parameter extraction (useParams). |
react-hook-form |
Registers inputs securely without triggering hundreds of re-renders per keystroke. |
yup |
Intercepts form submissions to enforce strict schema validation. |
recharts |
Transforms raw job data into dynamic, responsive SVG graphics. |
framer-motion |
Drives the liquid transitions, modal springing, and physical element behaviors. |
react-icons |
Injects infinitely scalable, colorable SVG icons directly into components. |
react-markdown |
Parses users' raw text notes into beautiful formatted lists and bold text. |
date-fns |
Safely parses and formats date strings natively. |
axios |
Preconfigured for API integrations defined in phase 2. |
src/
βββ components/
β βββ Charts/
β β βββ MonthlyBarChart.jsx
β β βββ PipelineDonut.jsx
β βββ ConfirmModal.jsx
β βββ JobCard.jsx
β βββ SearchBar.jsx
β βββ Filters.jsx
β βββ Sidebar.jsx
βββ context/
β βββ ApplicationContext.jsx
βββ hooks/
β βββ useApplications.js
β βββ useDebounce.js
β βββ useLocalStorage.js
βββ pages/
β βββ AddApplication.jsx
β βββ Analytics.jsx
β βββ Applications.jsx
β βββ Bookmarks.jsx
β βββ Dashboard.jsx
β βββ JobDetails.jsx
βββ services/
β βββ api.js (Mock data generator / Axios routing)
βββ utils/
β βββ helpers.js (ID generator, Date formatters)
βββ App.jsx (Layout logic & Router wrapper)
βββ index.css (Total CSS Variable Design System)
βββ main.jsx
Future developments to turn this frontend into a Full-Stack monolith:
- Backend Database Migration: Replace browser
localStoragewith a Node.js/Express + PostgreSQL backend. - Authentication: Secure Login/Signup via JWT logic or OAuth (Google/GitHub).
- Kanban Board View: A drag-and-drop Trello-style board (Applied β Interviewing β Offer).
- Browser Extension: A companion Chrome Extension to automatically scrape job details directly from LinkedIn.
- AI Resume Alignment: Allowing the user to upload a PDF Resume and compare it to Job Descriptions for an "Alignment Score".
This project successfully fulfills the standard Software Engineering evaluation metrics outlined in the primary PRD:
- React Architecture (25%): Implemented strict context separation, custom hooks, and isolated component folders.
- Feature Completeness (25%): 100% of PRD mandates fulfilled, including Asynchronous Mock API fetching and Markdown Support.
- State Management (20%): Eliminated manual prop-drilling with Context API synced smoothly with Local Storage.
- UI/UX Quality (15%): Constructed a premium dual-identity, accessible CSS architectural system. Added
framer-motionfor UX weight. - Code Quality (15%): Clean separation of utility logic, reusable styling tokens, and strongly enforced linting rules.
1. Clone the repository:
git clone https://github.com/yourusername/job-tracker.git2. Navigate & Install dependencies:
cd Job-Tracker
npm install3. Run the blazing fast development server:
npm run dev