A full-stack web app to track job and internship applications — log statuses, set follow-up reminders, and view your job search stats on a dashboard.
Stack: React (frontend) · Node.js + Express (backend) · MySQL (database) · JWT auth
- Signup / Login with JWT authentication
- Add, edit, delete, and view job applications
- Track status: Applied → Interview → Offer / Rejected
- Dashboard with stats and a pie chart breakdown
- Reminders for follow-ups
- Light/Dark theme toggle
- Profile management + account deletion
job-tracker/
├── backend/ → Node.js + Express + MySQL API
└── frontend/ → React app
- Node.js (v18+) installed
- MySQL installed and running locally
Open your MySQL client (Workbench, CLI, or XAMPP's phpMyAdmin) and run the SQL files in backend/migrations/ in order:
001_create_users.sql
002_create_jobs.sql
003_create_reminders.sql
This creates the job_tracker database and its tables.
cd backend
npm install
cp .env.example .envOpen .env and fill in your actual MySQL password and a random JWT secret string.
npm run devBackend runs on http://localhost:5000. Visit http://localhost:5000/api/health to confirm it's running.
Open a new terminal:
cd frontend
npm install
cp .env.example .env
npm startFrontend runs on http://localhost:3000.
- Go to
http://localhost:3000 - Click "Get Started" and create an account
- Add your first job application from the Dashboard or Applications page
Auth (/api/auth)
POST /register— create accountPOST /login— loginGET /me— get current user (requires token)
Jobs (/api/jobs) — all require auth token
GET /— list all applicationsGET /stats— status counts for dashboard chartGET /:id— single applicationPOST /— create applicationPUT /:id— update applicationDELETE /:id— delete application
Reminders (/api/reminders) — all require auth token
GET /— list remindersPOST /— create reminderPUT /:id— update reminderDELETE /:id— delete reminder
Users (/api/users) — all require auth token
PUT /profile— update name/emailDELETE /account— delete account
If you're using this as a portfolio project, be ready to explain:
- Why JWT is stored and sent via
Authorization: Bearer <token>header - How passwords are hashed with bcrypt before storage (never stored in plain text)
- Why the backend re-checks
user_idon every job/reminder query (prevents one user from accessing another user's data) - How the React Context API (
AuthContext,ThemeContext) avoids prop-drilling - How
ProtectedRouteblocks access to dashboard pages when not logged in
- Email notifications for reminders (utils/sendEmail.js is scaffolded but not wired up)
- Pagination/search on the Applications page
- Resume file upload
- Deploy: frontend → Vercel/Netlify, backend → Render/Railway, DB → PlanetScale/Railway MySQL