A full-stack web application for tracking personal income, expenses, and financial health. Built as Assessment 1 submission.
Add your deployment URL here after deploying
- User registration with name, email, and password
- JWT-based login/logout
- Protected routes (redirects to login if not authenticated)
- Persistent sessions via localStorage
- Add income and expense transactions
- Edit existing transactions
- Delete transactions with confirmation dialog
- Fields: type, amount, description, category, date, optional notes
- Pre-defined categories for income (Salary, Freelance, Investment, Gift, Business, Other Income)
- Pre-defined categories for expenses (Food & Dining, Transportation, Shopping, Entertainment, Health, Education, Utilities, Rent, Travel, Personal Care, Other Expense)
- Category icons for visual identification
- Net balance, total income, total expenses, savings rate cards
- Income vs Expenses area chart (monthly trend, last 6 months)
- Expense breakdown pie chart by category
- Top categories list with amounts
- Period filter: This Month / This Year / All Time
- Full-text search on transaction description
- Filter by type (income/expense)
- Filter by category
- Filter by date range (start date + end date)
- Pagination (20 per page)
- Clear all filters button
Frontend
- React 18 (Vite)
- React Router v6
- Recharts (data visualization)
- Axios (HTTP client)
- DM Serif Display + DM Sans (fonts)
Backend
- Node.js + Express
- MongoDB + Mongoose
- JWT (jsonwebtoken) for auth
- bcryptjs for password hashing
- express-validator for input validation
Deployment
- Frontend: Vercel / Netlify
- Backend: Render / Railway
- Database: MongoDB Atlas
- Node.js v18+
- MongoDB (local or Atlas URI)
cd backend
cp .env.example .env
# Edit .env with your MongoDB URI and JWT secret
npm install
npm run dev # development (nodemon)
npm start # productionEnvironment variables (backend/.env):
PORT=5000
MONGODB_URI=mongodb://localhost:27017/finance-tracker
JWT_SECRET=your_super_secret_jwt_key_here
JWT_EXPIRES_IN=7d
FRONTEND_URL=http://localhost:5173
cd frontend
cp .env.example .env
# Edit .env if your backend runs on a different port
npm install
npm run dev # development
npm run build # production buildEnvironment variables (frontend/.env):
VITE_API_URL=http://localhost:5000/api
From project root, open two terminals:
# Terminal 1 - Backend
cd backend && npm run dev
# Terminal 2 - Frontend
cd frontend && npm run devVisit http://localhost:5173
finance-tracker/
├── backend/
│ ├── src/
│ │ ├── index.js # Express app entry
│ │ ├── models/
│ │ │ ├── User.js # User schema
│ │ │ └── Transaction.js # Transaction schema
│ │ ├── routes/
│ │ │ ├── auth.js # Register, login, /me
│ │ │ ├── transactions.js # CRUD + summary
│ │ │ └── categories.js # Category listing
│ │ └── middleware/
│ │ └── auth.js # JWT verification
│ ├── .env.example
│ └── package.json
│
└── frontend/
├── src/
│ ├── App.jsx # Routes
│ ├── context/
│ │ └── AuthContext.jsx # Auth state
│ ├── pages/
│ │ ├── Login.jsx
│ │ ├── Register.jsx
│ │ ├── Dashboard.jsx # Charts + summary
│ │ └── Transactions.jsx # CRUD + filters
│ ├── components/
│ │ ├── Layout.jsx # Sidebar + nav
│ │ └── TransactionModal.jsx
│ └── utils/
│ ├── api.js # Axios instance
│ └── format.js # Currency, date helpers
├── .env.example
└── package.json
cd frontend
npm run build
# Deploy dist/ to Vercel
# Set VITE_API_URL env var to your backend URL- Connect GitHub repo
- Set build command:
cd backend && npm install - Set start command:
cd backend && npm start - Add environment variables in Render dashboard
- Create free cluster at mongodb.com/atlas
- Get connection string and set as
MONGODB_URI - Whitelist
0.0.0.0/0for Render's dynamic IPs
- Never commit
.envfiles — they are in.gitignore - JWT secret should be a long random string in production
- MongoDB Atlas uses IP whitelisting; restrict to your server IPs when possible
- Responsive design (mobile-friendly sidebar)
- Savings rate calculation on dashboard
- Pagination on transactions list
- Per-user data isolation (all queries scoped by
user._id) - MongoDB indexes for efficient filtering
- Input validation on both frontend and backend