A modern, responsive job portal UI for developers built with React, Vite, and Tailwind CSS.
- Overview
- Key Features
- Tech Stack
- Project Structure
- Pages & Components
- State Management
- Getting Started
- Environment Variables
- Deployment
DevHunt Frontend is the React-based client for the DevHunt job portal. It provides a dark-themed, responsive interface for two types of users:
- Students / Job Seekers — browse jobs, filter by category, apply, save, and track applications.
- Recruiters — register a company, post job listings, and manage applicants from an admin dashboard.
The app uses Redux Toolkit + redux-persist for global state (user session survives page refresh), Axios for API calls with cookies, and React Router v7 for client-side routing.
| Feature | Details |
|---|---|
| OTP Registration Flow | Register → Email OTP → Auto login on verify |
| Role-based UI | Students see browse/apply views; Recruiters see admin dashboard |
| Job Search & Filter | Keyword search + category filter on the Jobs page |
| Save Jobs | Bookmark any job; saved count shown in Navbar badge |
| AI Recommendations | "Similar Jobs" section powered by backend AI on every job detail page |
| Recruiter Admin Dashboard | Manage companies, post jobs, view applicants, update status |
| Profile Management | Update bio, skills, resume URL, and profile photo |
| Forgot / Reset Password | OTP-based password reset without re-authentication |
| Persistent Auth State | redux-persist keeps the user logged in after page refresh |
| Responsive Design | Mobile-first; full responsive layout with a hamburger menu |
| Layer | Technology |
|---|---|
| Framework | React 18 + Vite 6 |
| Styling | Tailwind CSS 3 + tailwindcss-animate |
| UI Components | Radix UI (Avatar, Dialog, Popover, Select, etc.) |
| Icons | Lucide React + React Icons |
| Animations | Framer Motion |
| State | Redux Toolkit 2 + redux-persist |
| Routing | React Router DOM v7 |
| HTTP Client | Axios (withCredentials for cookie auth) |
| Toast Notifications | Sonner |
| Build Tool | Vite 6 |
| Deployment | Vercel |
Frontend/src/
├── components/
│ ├── admincomponent/ # Recruiter-only pages
│ │ ├── AdminJobs.jsx # List of recruiter's posted jobs
│ │ ├── AdminJobsTable.jsx # Filterable table of jobs
│ │ ├── Applicants.jsx # Applicant list for a job
│ │ ├── ApplicantsTable.jsx # Table with status update controls
│ │ ├── Companies.jsx # List of recruiter's companies
│ │ ├── CompaniesTable.jsx # Filterable company table
│ │ ├── CompanyCreate.jsx # New company registration form
│ │ ├── CompanySetup.jsx # Update company details + logo
│ │ ├── PostJob.jsx # Create new job listing form
│ │ └── ProtectedRoute.jsx # Route guard (Recruiter role only)
│ │
│ ├── authentication/ # Auth pages
│ │ ├── Login.jsx # Login with role selector
│ │ ├── Register.jsx # Registration + optional photo upload
│ │ ├── ResetPassword.jsx # Forgot password → OTP entry
│ │ └── VerifyOtp.jsx # OTP verification page
│ │
│ ├── components_lite/ # Student-facing pages & shared UI
│ │ ├── Home.jsx # Landing page (redirects Recruiter to /admin)
│ │ ├── Header.jsx # Hero section with job search input
│ │ ├── Navbar.jsx # Responsive top navigation
│ │ ├── Footer.jsx # Site footer with links
│ │ ├── Jobs.jsx # Filterable job listing page
│ │ ├── Browse.jsx # Browse all jobs
│ │ ├── Description.jsx # Job detail + Apply button + AI recommendations
│ │ ├── JobCards.jsx # Reusable job card component
│ │ ├── LatestJobs.jsx # Latest jobs grid on Home page
│ │ ├── Categories.jsx # Job category chips / filter
│ │ ├── Filtercard.jsx # Sidebar filter panel
│ │ ├── Profile.jsx # Student profile page
│ │ ├── EditProfileModal.jsx # Inline profile edit modal
│ │ ├── AppliedJob.jsx # Student's applied jobs table
│ │ ├── SavedJobs.jsx # Bookmarked jobs page
│ │ ├── RecommendedJobs.jsx # AI similar jobs carousel on Description
│ │ ├── PrivacyPolicy.jsx # Privacy policy page
│ │ ├── TermsofService.jsx # Terms of service page
│ │ └── TermsAndConditions.jsx# Detailed T&C page
│ │
│ └── ui/ # Radix-based reusable primitives
│
├── hooks/ # Custom data-fetching hooks
│ ├── useGetAllJobs.jsx # Fetch + dispatch all public jobs
│ ├── useGetAllAdminJobs.jsx # Fetch recruiter's own jobs
│ ├── useGetAllAppliedJobs.jsx # Fetch student's applied jobs
│ ├── usegetAllCompanies.jsx # Fetch recruiter's companies
│ └── useGetCompanyById.jsx # Fetch single company by ID
│
├── redux/ # Global state slices
│ ├── store.js # Combined store + redux-persist config
│ ├── authSlice.js # user, loading state
│ ├── jobSlice.js # allJobs, savedJobs, singleJob, filters
│ ├── companyslice.js # companies, singleCompany
│ └── applicationSlice.js # applicants for a job
│
├── utils/
│ └── data.js # API endpoint base URL constants
│
├── App.jsx # React Router route definitions
└── main.jsx # React root + Redux Provider + PersistGate
/ (Home)
→ Header (search) → Categories → LatestJobs
→ Navbar: Home | Browse | Jobs | Saved Jobs
/Jobs
→ Filtercard (salary, location, role, type)
→ JobCards grid
/Browse
→ Full job listing with search
/description/:id
→ Job details, requirements, Apply button
→ RecommendedJobs (AI-powered)
/Profile
→ ProfileCard, skills, resume, applied jobs
→ EditProfileModal
/saved-jobs
→ Bookmarked job cards (persisted in Redux)
/verify-otp
→ OTP input after registration
/forgot-password
→ Email entry → OTP → new password
/admin/companies
→ CompaniesTable with search filter
/admin/companies/create
→ CompanyCreate form
/admin/companies/:id
→ CompanySetup (update details + logo)
/admin/jobs
→ AdminJobsTable with search filter
/admin/jobs/create
→ PostJob form
/admin/jobs/:id/applicants
→ ApplicantsTable with status dropdowns
Redux Toolkit manages four slices, all persisted to localStorage via redux-persist:
| Slice | Key State | Populated By |
|---|---|---|
auth |
user, loading |
Login / verifyOtp / logout actions |
job |
allJobs, savedJobs, singleJob, searchedQuery |
useGetAllJobs hook |
company |
companies, singleCompany |
useGetAllCompanies hook |
application |
applicants |
getApplicants API call in Applicants page |
Every page that needs remote data uses a custom hook:
// Example: any component that needs job data
const { loading, error } = useGetAllJobs();
const jobs = useSelector((state) => state.job.allJobs);The hook calls the API, dispatches to Redux, and returns loading/error state. Components stay clean — they just read from the store.
- Node.js 18+
- The backend running locally at
http://localhost:5001(or Vercel URL)
git clone https://github.com/kaioumdev/Job-Hunt-Frontend.git
cd Job-Hunt-Frontendnpm installOpen src/utils/data.js and update the base URLs:
// For local development (backend running on port 5001)
export const USER_API_ENDPOINT = "http://localhost:5001/api/user";
export const JOB_API_ENDPOINT = "http://localhost:5001/api/job";
export const APPLICATION_API_ENDPOINT = "http://localhost:5001/api/application";
export const COMPANY_API_ENDPOINT = "http://localhost:5001/api/company";
// For production (already set to Vercel URL)
// export const USER_API_ENDPOINT = "https://job-hunt-backend-phi.vercel.app/api/user";npm run devApp runs at http://localhost:5173
npm run buildOutput goes to dist/ — ready to deploy.
The project currently uses hardcoded API URLs in src/utils/data.js. For a more flexible setup, create a .env file:
VITE_API_BASE_URL=http://localhost:5001Then update data.js:
const BASE = import.meta.env.VITE_API_BASE_URL;
export const USER_API_ENDPOINT = `${BASE}/api/user`;
export const JOB_API_ENDPOINT = `${BASE}/api/job`;
export const APPLICATION_API_ENDPOINT = `${BASE}/api/application`;
export const COMPANY_API_ENDPOINT = `${BASE}/api/company`;git add .
git commit -m "chore: production deploy"
git push origin main- Go to vercel.com/new → import the repo
- Vercel auto-detects Vite and sets the build command to
vite build - Click Deploy
If you migrated to VITE_API_BASE_URL:
Project Settings → Environment Variables:
| Key | Value |
|---|---|
VITE_API_BASE_URL |
https://job-hunt-backend-phi.vercel.app |
CORS note: The backend's allowed origins list must include your Vercel frontend URL exactly. Check
allowedOriginsinBackend/index.js.
MIT © 2025 DevHunt