A full-stack job tracking web application built with the MERN stack. Register, log in, and manage your job applications — track statuses, filter and search, view monthly stats, and upload a profile avatar.
Live Demo: jobify.live
Frontend
- React 18 + Vite
- React Router v6 (loaders & actions)
- React Query v4 (data fetching & caching)
- Styled Components
- Recharts
- Axios
- React Toastify
Backend
- Node.js + Express
- MongoDB + Mongoose
- JSON Web Tokens (HTTP-only cookies)
- Cloudinary (avatar uploads)
- express-validator, bcryptjs, multer
- User registration & login with hashed passwords and JWT auth
- Role-based access: admin and user
- Create, read, update, and delete job applications
- Filter jobs by status, type, and keyword; sort by date or name
- Paginated job listings (10 per page)
- Monthly application stats with bar and area charts
- Profile page with avatar upload (Cloudinary)
- Dark mode (persisted via localStorage)
- Demo / test user for exploring the app without registering
- Rate limiting, helmet, and mongo-sanitize for security
- Node.js 18+
- MongoDB Atlas account (or local MongoDB)
- Cloudinary account (for avatar uploads)
# Clone the repository
git clone https://github.com/your-username/jobify.git
cd jobify
# Install all dependencies (root + client)
npm run setup-projectCreate a .env file in the project root:
NODE_ENV=development
PORT=5100
MONGO_URL=your_mongodb_connection_string
JWT_SECRET=your_jwt_secret
JWT_EXPIRES_IN=1d
CLOUD_NAME=your_cloudinary_cloud_name
CLOUD_API_KEY=your_cloudinary_api_key
CLOUD_API_SECRET=your_cloudinary_api_secret# Run both server and client concurrently
npm run dev- Server:
http://localhost:5100 - Client (Vite):
http://localhost:5173
npm run setup-production-app
node serverjobify/
├── client/ # React frontend (Vite)
│ ├── src/
│ │ ├── assets/ # Images, wrappers (Styled Components)
│ │ ├── components/ # Reusable UI components
│ │ ├── pages/ # Route-level pages
│ │ └── utils/ # customFetch, constants, links
│ └── vite.config.js
├── controllers/ # Express route handlers
├── errors/ # Custom error classes
├── middleware/ # Auth, validation, multer, error handler
├── models/ # Mongoose schemas (Job, User)
├── routes/ # Express routers
├── utils/ # JWT helpers, password utils, constants
└── server.js
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/auth/register |
Register a new user |
| POST | /api/v1/auth/login |
Login |
| GET | /api/v1/auth/logout |
Logout |
| GET | /api/v1/users/current-user |
Get logged-in user |
| PATCH | /api/v1/users/update-user |
Update profile + avatar |
| GET | /api/v1/users/admin/app-stats |
Admin: user & job counts |
| GET | /api/v1/jobs |
Get all jobs (with filters & pagination) |
| POST | /api/v1/jobs |
Create a job |
| GET | /api/v1/jobs/:id |
Get a single job |
| PATCH | /api/v1/jobs/:id |
Update a job |
| DELETE | /api/v1/jobs/:id |
Delete a job |
| GET | /api/v1/jobs/stats |
Monthly stats + status breakdown |
- Register a user and note their email.
- Edit
populate.jsto use that email. - Run:
node populateThis seeds the database with 100 mock jobs from utils/mockData.json.
The app is configured for deployment on Render.
Set the build command to:
npm run setup-production-app
And the start command to:
node server
Add all .env variables to Render's environment settings.
MIT