Investments in many places, no single number to trust.
Holdings sat across several exchanges, in several currencies, tracked in disconnected sources. Getting one true view of net worth meant reconciling numbers by hand, and history was guesswork.
- ×Holdings spread across exchanges
- ×Several currencies, converted by hand
- ×No reliable history
- ×Spreadsheets with extra steps
- →One consolidated portfolio
- →Live and historical FX conversion
- →Net worth charted from real dates
- →Investments, loans and spending in one app
What we built
A TypeScript app end to end, built with the most formal security and release process of anything on this site.
Portfolio
- →Overview with consolidated net worth
- →Holdings with transfers between portfolios
- →Dividends with reinvestment
- →Loans with repayments
- →Sub-portfolios with their own goals
Markets and insight
- →Live prices and FX rates
- →Historical prices imported in bulk
- →Net worth snapshots by date
- →Trading desk and cross-listed positions
- →Reports with export, and an AI assistant
Household money
- →Expense and income ledgers per household
- →Categories and payment methods
- →Monthly budgets for needs, wants and investments
- →A wealth plan: the pace needed to reach a target
My part
- →Full UI revamp and design tokens
- →Pre-login page and sign-in modal
- →Historical FX rates per snapshot date
- →Mobile pass and a full-repo correctness review
Security checks on every request
Real financial data lives here, so nothing reaches a route without passing the same checks in the same order, every time.
A short-lived token, held in memory and never in local storage.
Admin and co-manager actions are checked on the server.
Every request is scoped to portfolios the user can access.
Body, params and query are checked against a schema.
Engineering decisions
Refresh-token rotation
Long sessions without long-lived tokens sitting in the browser.
Hashed passwords
Passwords are hashed with bcrypt and never logged.
Schema on every route
Zod validation on every input, not just the sensitive ones.
Tested in CI
Vitest and Supertest run on GitHub Actions before anything merges.
Gated releases
Changes move through testing and review branches before main.
One deploy
Express serves the API and the compiled app from one service.



Holdings across accounts and currencies now add up to one number.
Holdings that lived across separate accounts now sit in one consolidated view, with history built from real transaction dates. Shown here with sample figures only.
