FolioFOLIOdocs
AppApp
BackendBackend
Mobile/Portfolio
01 / 08

Portfolio

Your financial snapshot

CoreReal timeCharts

Overview

This is the screen you land on every time you open the app. At the top you get the big number, your total portfolio value, updated in real time. Right below that is the day change. There is a time period chart (day, week, month, year, all time) that shows how your portfolio has moved. Below the chart you will find your holdings list with each asset showing its current price, your position size, and the gain or loss. You can switch between a list view and a pie chart view to see your allocation visually. There is also a top movers section, and an AI insight snippet powered by Claude.

How it works

1

When the screen loads, it pulls the active portfolio from the Zustand store (usePortfolioStore). The store holds all your portfolios, assets, and the currently selected portfolio ID.

2

For stocks and ETFs, we use React Query (useBulkQuotes) to batch fetch prices from our Supabase Edge Function, which proxies Alpha Vantage. This runs every 60 seconds automatically.

3

Crypto, forex, and commodities use a separate hook (useMultiAssetQuotes) because they need different API endpoints. These also refresh every 60 seconds.

4

All the prices get merged into a single prices map. That map gets passed to usePortfolioCalculations which computes the total value, day change, allocation percentages, and top movers.

5

The chart data comes from usePortfolioHistory, which fetches historical prices for each holding and combines them into a single portfolio timeline. The data gets downsampled to keep rendering smooth.

6

Pull to refresh triggers a refetch of all price data. The widget updater also runs here, pushing the latest portfolio data to iOS widgets whenever prices update.

Key decisions

React Query over manual fetching

We tried managing price fetching with useEffect and local state early on. It was a mess. Stale data, race conditions, no caching. React Query solved all of that with built in refetch intervals, deduplication, and background updates. The code got simpler and the UX got better.

Splitting bulk and individual quotes

Alpha Vantage has a batch endpoint for stocks and ETFs but not for crypto or commodities. So we split the fetching into two hooks. Stocks and ETFs go through useBulkQuotes (one API call for all of them), while crypto, forex, and commodities each get their own individual call through useMultiAssetQuotes.

Zustand for local state, not Context

We needed the portfolio store to be accessible both inside and outside React components (for the sync service, widget updater, etc). Zustand lets you call usePortfolioStore.getState() from anywhere. With Context you are stuck inside the React tree. That alone made the decision easy.

Pie chart vs list toggle

Some people want to see exact numbers. Others want a visual feel for their allocation. Instead of picking one, we added a toggle. The pie chart uses a custom SVG component that renders a donut chart with smooth animations.

Quick Reference

Routeapp/(tabs)/index.tsx
StoreusePortfolioStore, usePortfolioCalculations
APIsuseBulkQuotes, useMultiAssetQuotes, usePortfolioHistory
Components
BalanceHeaderChartCardHoldingsCardOverviewCardTopMoversSectionAIInsightSnippetPortfolioSelectorSheet
NextMarket