← Back to portfolio
Case Study · 16 / 17
Full-Stack · MERN · 2025

An expense tracker
with nothing extra.

Expense Analytics is a deliberately minimal MERN-stack tracker: add, edit, delete an expense, see the running total update instantly, and persist it all to MongoDB. A study in resisting feature creep and getting the core loop genuinely right.

Role
Solo — full-stack build
Pattern
MERN CRUD + analytics
Stack
React · Express · MongoDB · Tailwind
Status
Open-source project
Fig. 16 · add → list → total
16
The hard part of a simple app is keeping it simple.
§ 01 — The intent

Most trackers drown the one job you came for.

Expense apps love to sprawl — budgets, categories, recurring rules, charts three levels deep — and somewhere in there the actual task, "write down what I spent and see the total," gets buried. This project is a reaction to that: strip the tracker back to the loop that matters and make that loop feel instant.

It's also a clean MERN exercise — React, Express, MongoDB, wired end to end — where the discipline is doing the fundamentals well rather than piling on features.

A total that lags by a refresh isn't real-time — it's just late.

§ 02 — Constraints

The whole spec, honestly.

§ 03 — Architecture

Four layers, cleanly separated.

A React form and list talk to an Express API organised into routes, controllers, and a Mongoose model, with MongoDB underneath and a small analytics component deriving the totals.

01 — Form
React input
Add and edit expenses; Tailwind-styled, submits to the API.
02 — API
Express routes
Controller logic over Mongoose handles the CRUD lifecycle.
03 — Store
MongoDB
Expense schema persists every record for durable state.
04 — Analytics
Live total
A component derives the running total and re-renders on change.

Splitting the backend into config, controllers, models, and routes is overkill for an app this size — on purpose. It's the shape a larger service would take, practised where the stakes are low.

§ 04 — Where the care went

Keeping the UI and the total in sync.

The one bit of real state discipline is making sure the list and the analytics never disagree. Delete an expense and the total has to drop in the same beat — no manual refresh, no stale figure lingering. Getting that single source of truth right, so both the list and the total read the same data, is the difference between "feels instant" and "feels broken."

Everything else was resisting temptation: no category system, no charts library, no auth — because each of those would have blurred the one loop the app exists to nail.

4
CRUD operations, the complete lifecycle
1
Source of truth behind list and total
0
Refreshes needed to see an updated total
§ 05 — Design

Legible over clever.

Tailwind keeps the surface plain and readable — a form, a list, a total — with the theme adjustable in one config file. There's nothing to learn and nothing in the way, which for a personal expense tracker is exactly the point.

§ 06 — What I'd do differently

Three things, next time.