Private portfolio tracker for Indian and US investments. The repo is a pnpm/Turborepo monorepo with a Vercel-hosted Next.js app, a view-only Expo app, tRPC APIs, Clerk auth, Supabase Postgres/Storage, and upload-first portfolio importers.
apps/web: Next.js App Router web app and server API routes.apps/mobile: Expo Router app for read-only portfolio views from the active Convex backend. See mobile configuration and session behavior.
packages/api: tRPC routers, auth scoping, import orchestration.packages/db: Drizzle schema and database client.packages/importers: Tickertape, Vested/DriveWealth, and spreadsheet import contracts.packages/analytics: portfolio summary, allocation, and XIRR helpers.
- Install dependencies with
pnpm install. - Copy
.env.exampleto.env.localand fill Clerk, Supabase, and database credentials. - Create a private Supabase Storage bucket named
portfolio-imports. - Run
pnpm db:generateand apply migrations withpnpm db:migrate. - Start the web app with
pnpm dev:web. - Start the Expo app with
pnpm dev:mobile.
Original uploaded files are retained for 30 days by default. Normalized portfolio data remains until deleted from the app.
For fake local portfolio data without production records, see docs/local-development.md.
Holdings APIs return account-level positions. Accounts are identified by provider and account name within a Household. Two accounts holding the same symbol both contribute to holdings, totals, allocation and performance. A complete snapshot can exit an omitted position only within its source group. Position history and cash flows used for its XIRR stay scoped to that account.
The importer-defined workbook representations of US Stocks, Indian Stocks and Mutual Funds overlap with Vested or Tickertape respectively. Selection deduplicates those exact account/provider/source-type/sheet relationships; other accounts remain independent. US workbook and Vested complete snapshots also share omission semantics. Physical source snapshots, position keys and legacy detail aliases remain separate.
Convex publishes these selections when a portfolio version is built. Existing active versions retain their materialized selections until the next successful publication. This correction does not rewrite source facts or restore records removed by historical SQL cleanup migrations.
pnpm typecheck, pnpm typecheck:migration-tools, and compiler-only workspace builds use the exact [email protected] release in standard mode. Next.js, Expo, ESLint, and Convex retain JavaScript TypeScript for their own tooling. See compiler commands and compatibility notes.
apps/web is the only workspace that emits build artifacts (next build → .next/**); every other package's build is tsc-rs --noEmit, which exists purely to fail on type errors. So turbo.json defaults build outputs to [] and overrides only @investment-sync/web#build — otherwise Turbo logs a "no output files found" warning for each package on every uncached execution even though nothing is wrong.
If you add a workspace that does emit build artifacts, give it its own <package>#build override in turbo.json. A package#task entry replaces the generic task outright rather than merging into it, so the override must repeat dependsOn as well. Without one the package inherits outputs: [] and Turbo will report a cache hit while restoring nothing.