Single source of truth for net-worth history: Excel/Numbers import into SQLite, REST API, Vite + React dashboard (CLP/USD charts, class tabs, account detail).
server/ — Express + TypeScript + better-sqlite3; migrations in server/migrations/; DB file server/data/nw-tracker.db.client/ — Vite + React + TypeScript.cfraser/ — Numbers CSV exports + optional stocks-lots.csv, fund-unit-values.csv, etc.cfraser.xlsx — primary import workbook (path overridable via EXCEL_PATH).package.json — npm workspaces (server, client); scripts dev:server, dev:client, migrate, import:excel..nvmrc pins Node (keep in sync with root package.json engines.node).nvm use before installs or scripts if you use nvm..npmrc may set min-release-age (supply-chain). If npm install fails on a too-new package, pin an older release (e.g. Express was pinned to 4.21.2 exact) rather than disabling the policy long-term.server/src/db.ts opens the DB, runs initSchema() and runMigrations() at module load so any import of db runs migrations before modules that prepare() statements against migrated tables (e.g. equity_daily).npm run migrate (root) loads server/src/db.ts once to apply pending SQL migrations.equity_daily (ticker, trade_date, close_usd) for SPY/VEA EOD from Yahoo at import; fund_unit_daily (optional valor-cuota backfill via CSV).npm run import:excel (see server/scripts/import-excel-history.ts header comment for behavior).units in stocks-lots.csv: MTM CLP from equity_daily + brokerage_flows + fx_daily; import clears SPY/VEA valuations when MTM mode applies and refreshes equity_daily for SPY/VEA.monthEndDate in CSV helpers), not the first of the month.cfraser/fund-unit-values.csv: semicolon CSV, headers series_key, day, unit_value_clp, optional note — example keys: afp_uno_cuota_a, fintual_risky_norris, fintual_risky_norris_apv (charts still mostly use valuations unless wired to fund series).server/src/valuationTimeseries.ts builds dashboard and per–asset-group time series; brokerage tab merges SPY+VEA into stocks_total with optional crypto merge into crypto_total.getGroupValuationTimeseries): response includes synthetic lines __group_val_total and __group_dep_total (“Total (clase)” / “Total aportes acum.”) prepended to the series list. The main dashboard primary block (accounts_ex_property) does not add these totals.null until the first month cumulative deposits are non-zero, so lines do not sit at zero from the chart’s earliest date.cuenta_corriente: no cumulative deposit line (balance-only semantics).?granularity=daily for SPY/VEA MTM when equity_daily exists; monthly remains default.ValuationLineCharts.tsx (trimLeadingInactivePoints, deposit line naming via deposit_series_name); class tab page uses thickKey="__group_val_total" for the total valuation stroke.3001 (PORT env).tsx watch src/index.ts may ignore Ctrl+C in some setups; kill with lsof -iTCP:3001 / pkill -f "tsx watch src/index.ts" if needed.fund-unit-values.csv when needed.