All work

Expense Tracker

A full-stack personal finance app for tracking income, expenses, and savings with your own categories, monthly reports, and interactive charts.

React · TypeScript · Vite · Tailwind CSS · Radix UI · Recharts · React Hook Form · Zod · Express · Prisma · PostgreSQL · JWT

Expense Tracker

The problem

Most budget apps lock you into fixed categories and only split money two ways — in or out. Savings get counted as spending, so the numbers lie. I needed a model where savings is a first-class transaction type, categories are fully user-owned, and every report recomputes instantly as data changes.

The approach

I built a React + TypeScript SPA on Vite with Tailwind and Radix UI primitives, backed by an Express + Prisma + PostgreSQL API. Auth is email/password with a JWT in an httpOnly cookie. Transactions carry a three-way type (income / expense / savings) mirrored from their category for fast queries, and all reporting is derived client-side from a single transactions fetch — no reporting endpoints, no stale aggregates.

Architecture


    // Monorepo
    ├── /frontend                # React + Vite + TypeScript SPA
    │   └── /src
    │       ├── /pages           # Dashboard, Transactions, Categories, Reports, Settings, Login, Register
    │       ├── /charts          # Recharts: income vs expense, savings trend, category pie/bar
    │       ├── /components      # Reusable UI built on Radix primitives
    │       ├── /services        # Typed API client over /api
    │       ├── /context         # Auth + currency providers
    │       ├── /hooks           # Data fetching and derived-stat hooks
    │       └── /lib             # Types, formatters, transaction helpers
    └── /backend                 # Express + Prisma REST API
        ├── /src
        │   ├── /routes          # auth, categories, transactions
        │   ├── auth.ts          # JWT issue/verify, httpOnly cookie
        │   ├── defaults.ts      # Starter categories seeded on register
        │   └── prisma.ts        # Prisma client singleton
        └── /prisma              # schema.prisma + migrations (User, Category, Transaction)
    

What it moved

  • Three-way money model (income / expense / savings) makes savings rate an accurate, first-class metric instead of a mislabelled expense
  • User-owned categories with typed colors — rename, recolor, or delete without touching the schema
  • Zero reporting endpoints: dashboard, savings trend, and category breakdowns all derive from one cached fetch, so charts update the instant a transaction is added
  • End-to-end API smoke test (npm run smoke) covers the full auth → category → transaction flow
Expense Tracker, view 2
Expense Tracker, view 3