Full‑stack expense tracking app to manage personal finances, categorize spending, analyze trends, and digitize receipts with OCR.
Quick links:
- Live docs:
docs/USER_MANUAL.md(PDF‑ready) - Client:
client/(React 19 + React Router) - Server:
server/(Express 5 + MongoDB + JWT)
ExpenseTracker helps users record expenses, organize them by categories, monitor subscriptions, set goals, generate reports, analyze trends/forecasts/anomalies, and scan receipts (PDF/images) using OCR. The UI is responsive and optimized for desktop and mobile.
- Expense management: add, edit, delete, filter, search, sort
- Categories: CRUD with per‑user uniqueness
- Subscriptions: track recurring payments and reminders
- Goals: create savings/budget goals and monitor progress
- Reports: generate and view downloadable reports
- Analytics: trends, forecasts, anomalies, recommendations
- OCR for receipts: PDF/image uploads with parsing and text recognition
- Bank integration: Salt Edge connect session and transaction fetch
- Authentication: email/password + Google sign‑in, JWT protected API
- Responsive design: mobile‑friendly UI
- Client (
client/): CRA, React 19, React Router, Contexts (AuthContext,AnalyticsContext). Axios helpers insrc/services/api.jsandsrc/utils/api.js. JWT stored inlocalStorage. - Server (
server/): Express 5 (ESM), MongoDB via Mongoose, JWT auth, multer uploads, OCR via pdf-parse and tesseract.js. Routes mounted inserver/app.js.
API route mounts:
/api/users(auth/profile/password/google/forgot/reset)/api/expenses(CRUD,GET /stats,GET /chart)/api/categories/api/reports/api/receipts(uploads + OCR)/api/analytics/api/goals/api/subscriptions/api/bank
Prerequisites
- Node.js 18+ and npm
- MongoDB (local or Atlas)
- Clone
git clone https://github.com/mohammedelahmar/ExpenseTracker.git
cd ExpenseTracker- Install dependencies
cd server && npm install
cd ../client && npm install- Configure environment
- Server: copy
server/.env.exampletoserver/.envand fill values - Client: copy
client/.env.exampletoclient/.envand fill values
Key server env vars
PORT(default 5000)CONNECTION_URLMongo URIJWT_SECRETstrong secretCLIENT_URLe.g., http://localhost:3000PUBLIC_BASE_URLe.g., http://localhost:5000- Email creds:
EMAIL_USERNAME,EMAIL_PASSWORD,FROM_NAME,FROM_EMAIL - Google:
GOOGLE_CLIENT_ID - Bank:
SALT_EDGE_APP_ID,SALT_EDGE_SECRET
- Run locally
# Terminal A
cd server
npm run dev
# Terminal B
cd client
npm startThe client runs on http://localhost:3000 and proxies API to http://localhost:5000.
Screenshots are in screenshot/ — the full step‑by‑step manual with images is in docs/USER_MANUAL.md.
- Welcome and sign in: create an account or log in (email/password or Google)
- Dashboard: view total spend, recent expenses, charts
- Expenses: list, filter, search, sort; add/edit/delete and attach receipts
- Categories: manage custom categories
- Subscriptions: track recurring charges
- Goals: set targets and monitor progress
- Reports & Analytics
- OCR Receipts: upload PDF/JPEG/PNG; server scans, parses, and extracts merchant/date/amount
Server (Jest + Supertest)
cd server
npm test # run all tests locally using in-memory MongoDB
npm run test:watch
npm run test:ci # with coverage (used in CI)Client (Jest via react-scripts)
cd client
npm test -- --watchAll=falseEnd‑to‑end (Cypress)
# In one terminal start API
cd server
# Option A: use real Mongo
CONNECTION_URL=mongodb://localhost:27017/expense_e2e JWT_SECRET=dev npm start
# Option B: use in-memory Mongo (no Mongo install needed)
npm run start:mem
# In another terminal build & serve client
cd client
npm run build
npx serve -s build -l 3000
# Then run Cypress in headless mode
npm run cypress:runOCR verification
- Upload a known sample receipt and verify extracted fields on the form preview before saving.
GitHub Actions
- Workflow
.github/workflows/ci.yml:- Installs and tests server with Jest on Node 18
- Installs and tests client with Jest
- Builds client, starts API and static server, runs Cypress E2E in headless mode
- Uses a MongoDB service in CI; workflow fails if any test fails
Build
cd client && npm run buildHost the API
- Render, Railway, Fly.io, or a VPS. Expose port
PORT, set env vars, and persistuploads/(use a volume or S3‑style storage).
Host the client
- Vercel or Netlify: deploy
client/buildand setREACT_APP_API_URLto your API’s public URL (or configure a proxy).
Security considerations
- Use HTTPS everywhere (client and API)
- Keep
JWT_SECRETstrong and private - Validate and sanitize all inputs (server uses validators)
- Limit upload size; scan PDFs/images (receipts pipeline already checks size/JS/embeds)
- Configure CORS to your domains
- Store JWT in memory or localStorage with care (avoid XSS)
- Server won’t start: check
CONNECTION_URL, MongoDB availability, and.env - 401/403 errors: ensure
Authorization: Bearer <token>header is present; re‑login - CORS blocked: set
CLIENT_URLand redeploy; verify origin matches - OCR fails: ensure PDFs/images are clear; keep
eng.traineddataavailable; setPUBLIC_BASE_URL - Broken images: verify
/uploadsis served andPUBLIC_BASE_URLpoints to API origin
- Expand Cypress E2E coverage (more user journeys, OCR fixtures)
- Multi‑currency support and FX conversion
- Shared budgets and household accounts
- Plaid alternative connector in addition to Salt Edge
- OCR accuracy depends on receipt quality; manual corrections may be needed
- Bank integration requires valid Salt Edge credentials and may be region‑limited
See docs/DELIVERY.md for step‑by‑step instructions to produce clean source and distribution archives.
MIT — see LICENSE.
— Maintainer: Mohammed El Ahmar