Skip to content

MANICHELLURII/job-portal

Repository files navigation

Job Portal

A full-stack job portal web application with role-based access for Candidates, Employers, and Admins. Built with React, Node.js, Express, and PostgreSQL.

Tech Stack

Layer Technology
Frontend React 19 (Vite) + Tailwind CSS
Backend Node.js + Express.js
Database PostgreSQL
Auth JWT (access token + refresh token via httpOnly cookie)

Features

Candidate:

  • Browse jobs with search, location filter, type filter, and pagination
  • View full job details and apply with one click
  • Track application status (applied → reviewed → accepted/rejected)
  • Edit profile (name, skills, resume URL, bio)

Employer:

  • Post, edit, and delete job listings
  • View applicants for each listing with full profile info
  • Update applicant status via inline dropdown

Admin:

  • View all registered users
  • Delete any job listing

Auth & Security:

  • JWT access token (15min, in-memory) + refresh token (7d, httpOnly cookie)
  • Passwords hashed with bcrypt (10 salt rounds)
  • Role-based route protection on both frontend and backend
  • CORS origin configurable via environment variable

ER Diagram

┌──────────────┐       ┌──────────────┐
│    users     │       │   profiles   │
├──────────────┤       ├──────────────┤
│ id (PK)      │──1:1──│ id (PK)      │
│ name         │       │ user_id (FK) │
│ email (UQ)   │       │ skills       │
│ password_hash│       │ resume_url   │
│ role         │       │ bio          │
│ created_at   │       └──────────────┘
└──────┬───────┘
       │
       │1:N                    1:N
       ▼                        ▼
┌──────────────┐       ┌────────────────┐
│    jobs      │       │  applications  │
├──────────────┤       ├────────────────┤
│ id (PK)      │──1:N──│ id (PK)        │
│ employer_id  │       │ candidate_id   │
│ title        │       │ job_id (FK)    │
│ description  │       │ status         │
│ location     │       │ applied_at     │
│ type         │       │ UQ(cand, job)  │
│ deadline     │       └────────────────┘
│ created_at   │
└──────────────┘

Project Structure

/client                    → React frontend (Vite)
  /src
    /components            → Navbar, ProtectedRoute
    /context               → AuthContext (session management)
    /pages                 → All page components
    /utils                 → api.js (fetch wrapper with 401 retry)

/server                    → Express backend
  /config                  → db.js, init.sql, seed.sql
  /controllers             → Business logic per feature
  /middleware              → JWT auth middleware
  /models                  → PostgreSQL queries (parameterized)
  /routes                  → API endpoint definitions
  server.js                → Entry point

.env.example               → Environment variable template

Setup Instructions

Prerequisites

  • Node.js 18+
  • PostgreSQL 14+

1. Clone the repo

git clone https://github.com/yourusername/job-portal.git
cd job-portal

2. Set up environment variables

cp .env.example .env
# Edit .env with your PostgreSQL credentials and secrets

3. Create and seed the database

psql -U postgres -c "CREATE DATABASE jobportal;"
psql -U postgres -d jobportal -f server/config/init.sql
psql -U postgres -d jobportal -f server/config/seed.sql

Seed data: 1 admin, 2 employers, 3 candidates, 5 jobs, 6 applications. All seed users have password: password123

Email Role
admin@jobportal.com admin
hr@techcorp.com employer
jobs@startupxyz.com employer
alice@email.com candidate
bob@email.com candidate
charlie@email.com candidate

4. Install dependencies & run

# Terminal 1 — Backend
cd server
npm install
npm run dev

# Terminal 2 — Frontend
cd client
npm install
npm run dev

The backend runs on http://localhost:5000 and frontend on http://localhost:5173.

API Endpoints

Auth

Method Route Description Auth Required
POST /api/auth/register Register new user No
POST /api/auth/login Login, get tokens No
POST /api/auth/refresh Refresh access token Cookie
POST /api/auth/logout Clear refresh cookie No
GET /api/auth/me Get current user Yes

Jobs

Method Route Description Auth Required
GET /api/jobs List jobs (paginated, filterable) No
GET /api/jobs/:id Get single job No
POST /api/jobs Create a job listing Employer
PUT /api/jobs/:id Update a job listing Employer (owner)
DELETE /api/jobs/:id Delete a job listing Employer/Admin
GET /api/jobs/employer/me Get employer's own listings Employer

Pagination: GET /api/jobs?page=1&limit=10&search=react&location=bangalore&type=full-time

Response includes: { success, data, pagination: { page, limit, total, pages } }

Applications

Method Route Description Auth Required
POST /api/applications Apply to a job Candidate
GET /api/applications/me Get my applications Candidate
GET /api/applications/job/:jobId Get applicants for a job Employer (owner)
PUT /api/applications/:id/status Update application status Employer (owner)

Profile

Method Route Description Auth Required
GET /api/profile Get own profile Yes
PUT /api/profile Update profile Yes

Admin

Method Route Description Auth Required
GET /api/admin/users List all users Admin
DELETE /api/admin/jobs/:id Delete any job Admin

Security Notes

JWT Token Strategy:

  • Access token → stored in JavaScript memory (not localStorage) — short-lived (15 min)
  • Refresh token → stored in httpOnly, secure, sameSite cookie — long-lived (7 days)
  • This mitigates XSS attacks since the refresh token is inaccessible to JavaScript
  • On access token expiry, the frontend automatically attempts a silent refresh via the cookie

Known limitation: In-memory token is lost on page refresh, requiring a re-authentication via the refresh cookie. This is an intentional security tradeoff.

Deployment

Backend (Railway or Render)

  1. Push to GitHub
  2. Connect repo to Railway or Render
  3. Set environment variables (DATABASE_URL, JWT_SECRET, JWT_REFRESH_SECRET, CLIENT_URL)
  4. Deploy — use npm start as the start command

Database (Railway or Supabase)

  1. Create a PostgreSQL instance on Railway or Supabase
  2. Run init.sql and optionally seed.sql against the remote database
  3. Copy the connection string to your DATABASE_URL env var

Frontend (Vercel)

  1. Connect the /client directory to Vercel
  2. Set the API URL in the frontend code or as an env var
  3. Deploy

Live Demo: [Add your deployed URL here]

Screenshots

Add screenshots of your running application here:

  • Login page
  • Job listings with search and filters
  • Job detail page
  • Candidate dashboard (application tracking)
  • Employer dashboard (job management)
  • Applicants view with status management
  • Admin panel

Future Improvements

  • Email verification on registration
  • File upload for resumes (S3/Cloudinary)
  • Password reset via email
  • WebSocket notifications for application status changes
  • More granular admin controls (ban users, analytics)
  • Unit and integration tests (Jest + Supertest)
  • Rate limiting on auth endpoints

License

MIT

About

A full-stack job portal web application with role-based access for **Candidates**, **Employers**, and **Admins**. Built with React, Node.js, Express, and PostgreSQL.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages