Localhost investment tracker for broker-mirrored portfolios. The app uses a React/Vite frontend, Clerk authentication, Convex backend functions/storage, Bun tooling, and Biome formatting.
See docs/STATUS.md for what's shipped, deferred, and planned.
| Surface | Purpose |
|---|---|
| Overview | Portfolio value, day P&L, total return, allocation, top movers, and performance snapshots. |
| Platforms | Add brokers exactly as named, including eToro and Trade Republic. |
| Transactions | Add buys and sells manually; sells close positions through the same immutable ledger. |
| Import | Paste or upload CSV rows with date, symbol, units, price, optional side, currency, fees, and platform. |
| Holdings | Broker-grouped positions with average cost, live price, market value, and unrealised P&L. |
| Alerts | Price thresholds with in-app notifications. |
| Assistant | Convex action-backed portfolio summary chat surface. |
- Package manager: Bun
- Formatter: Biome
- Frontend: React + Vite + Wouter + shadcn-style UI
- Auth: Clerk via
@clerk/clerk-react - Backend: Convex queries, mutations, actions, HTTP actions, and scheduled cron
- Pricing: direct Yahoo Finance chart endpoint from Convex actions
bun install
bun run devbun run dev starts both Vite and the Convex dev process. Use
bun run dev:vite or bun run dev:convex if you need to run either side on
its own.
Run checks:
bun run check
bun run test
bun run build
bun run test:e2ePlaywright uses Clerk testing mode against the real Clerk test instance. Set
VITE_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY, TEST_USER_A, and
TEST_USER_B in .env.local before running browser tests. The TEST_USER_*
accounts must already exist in that Clerk test instance; Playwright signs in as
those users rather than provisioning them or using a local auth bypass. The
auth setup Playwright project writes the authenticated browser state to
.playwright/.clerk/user.json, and the Chromium project reuses that state for
the E2E specs.
The current dev deployment is linked through .env.local. The Convex project is
owned by the omnipotency-ai team. Required deployment env vars:
CLERK_JWT_ISSUER_DOMAINCRON_SECRETE2E_TEST_MODE=truefor the dev deployment used by Playwright
The scheduled job is defined in convex/crons.ts; the guarded HTTP entrypoint
is POST /api/cron/refresh-prices.