Overview β’ Features β’ Tech Stack β’ Architecture β’ Getting Started β’ API Reference β’ Contributing
ExpireX is a full-stack MERN (MongoDB, Express, React, Node.js) application that helps individuals and small businesses keep track of perishable or time-sensitive inventory β food, medicine, cosmetics, documents, anything with a shelf life.
The app automatically flags items that are fresh, expiring soon, or expired, sends email reminders on a schedule, and gives you a clean dashboard with charts to visualize your inventory health at a glance.
π‘ Built with a clean MVC (ModelβViewβController) architecture on the backend and a modern component-based React frontend β designed to be easy to read, extend, and deploy.
π Live Demo Β Β·Β API Base URL
π₯ Tip: Record a 10β15s screen capture of the dashboard/add-item flow, convert it to a GIF (ScreenToGif / Kap), drop it in a
docs/or.github/assets/folder, and embed it below β a live animated preview is the single highest-impact thing you can add for recruiters skimming your repo.
| π Auth | JWT-based register/login, forgot & reset password via email |
| π¦ Inventory CRUD | Add, edit, delete, and search items with category & quantity tracking |
| β° Expiry Intelligence | Auto-classification into Fresh, Expiring Soon, and Expired |
| π Notifications | In-app notification bell + automated email reminders via cron jobs |
| ποΈ Auto Cleanup | Scheduled job archives expired items and removes stale entries |
| π Dashboard | Bar & pie charts (Chart.js) showing category distribution and status breakdown |
| π Theming | Light/dark mode via React Context |
| π± Responsive UI | TailwindCSS + Framer Motion for a smooth, mobile-friendly experience |
| π CI/CD Ready | GitHub Actions workflow to install, build, and test on every push |
| Layer | Technology |
|---|---|
| Frontend | React 19, Vite, React Router 7, TailwindCSS, Chart.js, Axios, Framer Motion, React Hot Toast |
| Backend | Node.js, Express 4, JWT, Bcrypt.js |
| Database | MongoDB with Mongoose ODM |
| Scheduling | node-cron |
| Nodemailer (Gmail transport) | |
| CI/CD | GitHub Actions |
| Deployment | Render (API) Β· Vercel (Client) |
ExpireX is split into two independent apps that talk to each other over a REST API:
ExpireX/
βββ backend/ β Node + Express API (MVC pattern)
βββ frontend/ β React + Vite SPA (Component/Context pattern)
backend/
βββ models/ # M β Mongoose schemas (data + validation)
β βββ User.js
β βββ Item.js
β βββ ExpiredItem.js
β βββ Notification.js
β
βββ controllers/ # C β Business logic that talks to Models
β βββ authController.js (register, login, profile , password reset)
β βββ itemController.js (CRUD for inventory items)
β βββ expiredController.js (fetch archived/expired items)
β βββ notificationController.js (list, read, delete notifications)
β βββ dashboardController.js (aggregate stats for charts)
β
βββ routes/ # HTTP endpoints β wire URLs to Controllers
β βββ authRoutes.js β /api/auth
β βββ itemRoutes.js β /api/items
β βββ expiredRoutes.js β /api/expired
β βββ notificationRoutes.jsβ /api/notifications
β βββ dashboardRoutes.js β /api/dashboard
β
βββ middleware/
β βββ authMiddleware.js # protects routes via JWT (req.user)
β βββ errorMiddleware.js # centralized error handler
β
βββ services/
β βββ emailService.js # nodemailer templates (welcome, reminder, reset)
β
βββ cron/
β βββ expiryReminderCron.js # daily job β emails users about items expiring soon
β βββ deleteExpiredCron.js # daily job β archives/removes expired items
β
βββ config/
β βββ db.js # MongoDB connection
β βββ mailConfig.js # Nodemailer transporter setup
β
βββ app.js # Express app: middleware + route mounting
βββ server.js # Entry point: connects DB, starts cron jobs, starts server
Request lifecycle (the "V" is the JSON response consumed by React):
Client (React)
β axios request + JWT
βΌ
Route βββΆ Middleware (authMiddleware) βββΆ Controller βββΆ Model (Mongoose) βββΆ MongoDB
β² β
βββββββββββββββββββββββββββ JSON response βββ errorMiddleware βββββββββββββββββββββββββ
βΉοΈ Note:
expiredRoutes.jsexists in the codebase to expose expired-item history; make sure it's mounted inapp.js(app.use("/api/expired", expiredRoutes)) if you want that endpoint active.
frontend/src/
βββ pages/ # Route-level screens (Dashboard, ItemList, Login, Profile...)
βββ components/
β βββ common/ # Reusable UI: Button, InputField, Loader, ExpiryBadge...
β βββ layout/ # Navbar, Sidebar, Footer, DashboardLayout
β βββ dashboard/ # ItemCard, ItemForm, BarChartCard, PieChartCard...
βββ context/ # AuthContext, ThemeContext, NotificationContext
βββ services/ # api.js (axios instance) + authService/itemService/...
βββ hooks/ # useFetch, useDebounce, usePagination, useLocalStorage...
βββ routes/ # AppRoutes.jsx β route definitions + ProtectedRoute
βββ utils/ # constants, validators, expiryUtils, helpers
- Node.js β₯ 18 (project tested with Node 20)
- MongoDB β local instance or a free MongoDB Atlas cluster
- A Gmail account (with an App Password) for sending emails β or swap
mailConfig.jsfor another provider
git clone https://github.com/<your-username>/ExpireX.git
cd ExpireXcd backend
npm installCreate a .env file inside backend/:
PORT=5000
MONGO_URI=your_mongodb_connection_string
JWT_SECRET=your_super_secret_jwt_key
EMAIL_USER=your_gmail_address@gmail.com
EMAIL_PASS=your_gmail_app_password
FRONTEND_URL=http://localhost:5173
NODE_ENV=developmentRun the API:
npm run dev # nodemon, hot-reload
# or
npm start # plain nodeThe server boots on http://localhost:5000, connects to MongoDB, and starts both cron jobs (expiry reminders + expired-item cleanup).
Open a new terminal:
cd frontend
npm installCreate/update .env inside frontend/:
VITE_API_URL=http://localhost:5000/apiRun the client:
npm run devVisit http://localhost:5173 in your browser. π
# frontend
cd frontend
npm run build # outputs to frontend/dist
# backend β just run
cd backend
npm start| Cron Job | File | What it does |
|---|---|---|
| Expiry Reminder | cron/expiryReminderCron.js |
Runs daily, scans items nearing their expiry date, and emails the owner a reminder |
| Expired Cleanup | cron/deleteExpiredCron.js |
Runs daily, moves items past their expiry date into the ExpiredItem archive and cleans active listings |
Base URL: http://localhost:5000/api
π Auth β /auth
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /auth/register |
Register a new user | β |
| POST | /auth/login |
Log in, receive JWT | β |
| GET | /auth/profile |
Get current user profile | β |
| PUT | /auth/profile |
Update profile | β |
| PUT | /auth/change-password |
Change password | β |
| POST | /auth/forgot-password |
Request password reset email | β |
| POST | /auth/reset-password/:token |
Reset password with token | β |
π¦ Items β /items
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /items |
Add a new item | β |
| GET | /items |
List all items for the user | β |
| GET | /items/:id |
Get a single item | β |
| PUT | /items/:id |
Update an item | β |
| DELETE | /items/:id |
Delete an item | β |
ποΈ Expired β /expired
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /expired |
List archived/expired items | β |
π Notifications β /notifications
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /notifications |
List notifications | β |
| PUT | /notifications/read-all |
Mark all as read | β |
| PUT | /notifications/:id |
Mark one as read | β |
| DELETE | /notifications/:id |
Delete a notification | β |
π Dashboard β /dashboard
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /dashboard/stats |
Aggregate stats: total items, fresh/expiring/expired counts, category distribution | β |
β = requires
Authorization: Bearer <token>header (set automatically by the frontendAuthContextafter login).
A GitHub Actions workflow (.github/workflows/ci-cd.yml) runs on every push to main:
- Checks out the code
- Installs backend dependencies + runs tests (if present)
- Installs frontend dependencies
- Builds the frontend
- Reports pipeline success β
- Barcode/QR scanning for quick item entry
- Push notifications (Web Push / mobile)
- Multi-user households / shared inventories
- Export inventory reports (CSV/PDF)
- Unit & integration test suite
Contributions are what make the open-source community amazing! Any contributions are greatly appreciated.
- Fork the project
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Distributed under the MIT License. See LICENSE for more information.