AS.
← Back to work

02 / 11

Full Stack

WealthDeck

A self-hosted personal finance command center for Pakistani investors.

ROLE
Full-stack developer, solo project
TIMELINE
2026, ongoing
BUILT FOR
Personal use — tracking my own portfolio across every asset class I hold
STACK
Next.js 14 (App Router, client-only shell) · React 18 · TypeScript · Tailwind CSS · Radix UI · Framer Motion · Recharts · Node.js · Express · Prisma 5 · PostgreSQL (Supabase)
PLATFORM
Web app, publicly shareable with a safe read-only demo mode
Wealth Deck — sign in

THE PROBLEM

My money was spread across a dozen places with no common currency between them: PSX stocks in a brokerage app, crypto on an exchange, gold and silver in a spreadsheet, a provident fund statement from HR once a year, a voluntary pension scheme, an emergency fund, a few mutual fund goals, Zakat due once a year, and a monthly salary that had to be split between expenses and investing before any of that other tracking even started.

None of those tools talk to each other. None of them answer the one question that actually matters: what is everything worth, right now, and is it growing?

THE IDEA

Build one dashboard that owns the answer. Every asset class gets its own page with its own purchase/sale history, but they all roll up into a single net-worth number, computed server-side so the logic lives in one place instead of being recalculated differently on every screen.

Beyond the pages shown here, it also covers Gold & Silver, Mutual Funds, SPUS, a Provident Fund and VPS retirement dashboard, an Emergency Fund target, recurring Subscriptions with per-seat splitting, and a Schedule Planner for upcoming financial actions.

A tool only I would use daily has to be fast to open, trustworthy with real money, and honest about what's demo data versus what's mine.

WHAT IT DOES

01

Dashboard: net worth, in focus

One screen answers "how am I doing": total net worth against invested capital, today's and all-time change, a diversification score, a growth chart with configurable ranges, allocation by asset class, performance by category against a blended benchmark, and progress against a target allocation plan.

wealthdeck.vercel.app
Wealth Deck — Dashboard: net worth, in focus

02

PSX Stocks

Pakistan Stock Exchange holdings with buy/sell history, dividends, a watchlist, and realized P/L preserved even after a position is fully closed.

wealthdeck.vercel.app
Wealth Deck — PSX Stocks

03

Cryptocurrency

Purchases and sales with realized vs. unrealized profit split on an average-cost basis, a live price refresh, and USDT→PKR conversion tracked separately so FX movement doesn't get mistaken for coin performance.

wealthdeck.vercel.app
Wealth Deck — Cryptocurrency

04

Salary Allocation

A monthly worksheet that splits income into expenses and investments by percentage or fixed amount, carried forward month to month.

wealthdeck.vercel.app
Wealth Deck — Salary Allocation

05

Ledger

Multiple named ledgers (e.g. a renovation) with events and line-item entries, so a big one-off spend doesn't get lost in a single flat list.

wealthdeck.vercel.app
Wealth Deck — Ledger

06

Zakat, done properly

Zakat across the whole portfolio against the silver Nisab threshold, with the Hijri calendar date it becomes due and a full breakdown of how the number was reached — not just a total.

wealthdeck.vercel.app
Wealth Deck — Zakat, done properly

HOW IT WORKS

Browser ──► Next.js (client-rendered shell, reads theme/privacy from localStorage)
               │
               └── /api/* rewritten to ──► Express API ──► Prisma ──► PostgreSQL (Supabase)
                                              │
                                              ├── Price updaters (PSX, crypto, gold, silver, SPUS)
                                              ├── Intelligence service (net worth, diversification, trend)
                                              └── node-cron: snapshots, scheduled portfolio emails

One intelligence endpoint, not twelve reimplementations

Every page could have computed its own slice of "what's this worth," but net worth, diversification and day-change all live in one intelligence.service.ts so the dashboard and every detail page agree with each other by construction, not by convention.

Demo mode is a read-only mirror, not a toggle

Signed-out visitors get seeded demo data from the same endpoints the real data uses. A single-user login (env-configured credentials) unlocks the real portfolio; nothing about the UI branches on auth except the demo banner and the write permissions underneath it.

A computed ledger, not a running balance

Funds like the Provident Fund and Mutual Funds don't store a cached current value — they store transactions (contributions, NAV changes, a configurable profit rate) and compute the current value from that ledger every time. It's slower than a cached column, but it can never drift out of sync with its own history.

CHALLENGES AND WHAT I LEARNED

Prisma's dev migration flow fought the live database

The project runs against a live Supabase Postgres, and prisma migrate dev kept failing against it over the network. The fix was changing habit, not tooling: write the schema change, run prisma migrate diff to generate the SQL by hand, review it, then prisma migrate deploy. Slower, but every migration gets read now instead of trusting a shadow database that couldn't be fully controlled.

Categorization stayed boring on purpose

Early on there was a temptation to route transaction categorization through an LLM. It stayed rule-based instead — deterministic, free to run, and auditable. If a stock gets miscategorized, the rule can be grepped and fixed directly; an LLM call would have made that a guessing game, for a cost the project doesn't need to carry.

A serverless host doesn't like a PDF parser

The backend deploys as a Vercel function, and pulling in pdf-parse (which drags in pdfjs) crashed the function at boot because it expects a DOMMatrix that doesn't exist outside a browser. Lazy-loading the parser behind a stub, imported only when a PDF-handling route actually fires, keeps the rest of the API from paying for a dependency it doesn't need on every cold start.

Free tier, deliberately

Vercel ×2 (frontend and backend) and Supabase Postgres, all on free tiers. That constraint shaped real decisions — no LLM tier, no Redis, snapshots taken opportunistically on dashboard reads instead of a dedicated worker — and the app is faster for it, not slower.

RESULTS

Tracks 8 asset classes end to end: PSX stocks, crypto, gold, silver, mutual funds, SPUS, provident fund and VPS.

One dashboard replaces what used to be a brokerage app, an exchange, a spreadsheet, and a yearly HR statement.

Runs entirely on free-tier infrastructure, with no recurring cost.

Safe to share publicly: the live link is demo-data-only until sign-in.

STACK

Next.js 14React 18TypeScriptTailwind CSSRadix UIFramer MotionRechartsNode.jsExpressPrisma 5PostgreSQL (Supabase)

LINKS

NEXT PROJECT

GitHub Defect Marker

→

05 / CONTACT

Let'sbuild
somethinggreat.