React + Vite frontend with a local-JSON-backed API (Vite middleware) for tracking portfolio holdings, contributions/withdrawals, recurring contribution plans, and a forecast chart comparing the portfolio's real value against a same-contributions S&P 500 benchmark. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Investment Visualizer
A personal investment dashboard: track contributions, see asset allocation, and compare your portfolio's performance against the S&P 500.
Stack
- Frontend: React + TypeScript + Vite, charts with Recharts.
- Backend: a small REST API implemented as a Vite dev-server middleware
(
server/apiPlugin.ts) backed by local JSON files indata/. No database, no separate process —npm run devstarts both. - Data: everything lives under
data/*.json. The API layer (src/api/client.ts) is the only place that knows the data lives in local files — swapping it for a real backend later means only changing that file.
Data model (data/)
-
portfolio.json— current holdings snapshot (values, asset class, region, RV/RF allocation). -
history.json— periodic total-account-value snapshots, used to compute time-weighted return (TWR). Add more snapshots over time for a more accurate performance line. -
contributions.json— the movements ledger (external contributions/ withdrawals plus internal fund subscriptions/redemptions) and recurring contribution plans (weekly/monthly/etc.) used to project future cash flows. -
settings.json— portfolio inception date, forecast horizon (years), and the assumed annual return used for the projected part of the chart (historical TWR-derived or a manual assumption). -
sp500.json— cached daily S&P 500 closes, refreshed with:node scripts/fetch-sp500.mjs
Performance methodology
- Portfolio return: simplified chain-linked time-weighted return (TWR)
computed from
history.jsonsnapshots and external cash flows incontributions.json. Internal fund subscriptions/redemptions net to zero on total account value and don't affect it. - S&P 500 line: percentage change of the index since the portfolio's inception date, for an apples-to-apples "who's outperforming whom" comparison against the portfolio's TWR line.
- Forecast segment: continues the portfolio line past today using either the historical annualized TWR or a manual rate, applied to the current value plus projected future contributions from active recurring plans.
- 0% baseline: cumulative net contributions (actual + projected) with no investment return at all — the reference line for "what if it just sat in cash."
Development
npm install
npm run dev
This starts Vite (frontend + local JSON API) on http://localhost:5173.