Portfolio Tracking & Wealth Intelligence Platform
KuberOne is a self-hosted, family-scoped portfolio tracking platform. A family account is created at registration and the admin can invite members. Each member tracks holdings across multiple investment accounts and asset classes with real-time market data from Yahoo Finance.
- Family Workspace — Single family account with admin and member roles; admin invites members who set their own password via activation token
- Multi-Account Portfolio — Organize holdings into named investment accounts per member, each with its own currency and drag-to-reorder support
- Multi-Asset Tracking — Stocks, ETFs, REITs, Mutual Funds, Bonds, Gold, Silver, Crypto
- Real-Time Market Data — Powered by Yahoo Finance (free, no API key required), with batch price fetch and TTL cache
- P&L Calculation — Automatic profit/loss and return % with current market prices, FX-normalized to family base currency
- Portfolio Dashboard — Summary tiles, performance trendline, top 5 lifetime gainers/losers, top 5 daily gainers/losers
- Holdings Table — Sortable, per-account filterable, with CSV/Excel import
- Backup & Restore — Export all accounts and holdings to a JSON file; restore with replace or append mode
- Dark Mode — System-aware with manual toggle
- Mobile Responsive — Optimized for phones and tablets
- Secure Auth — JWT access + refresh tokens with JTI rotation and token versioning
- Self-Hosted — Runs entirely in Docker with no external dependencies
- FastAPI (Python) — REST API
- PostgreSQL — Relational database
- SQLAlchemy — ORM
- JWT (python-jose) — Access + refresh token auth with JTI rotation
- bcrypt — Password hashing
- yfinance — Yahoo Finance integration
- React 18 + TypeScript — UI
- Vite — Build tool
- Tailwind CSS — Styling
- Zustand — Auth + price cache state (persisted to localStorage)
- react-hook-form — Form handling
- Axios — HTTP client with 401 interceptor and refresh retry
- Docker + Docker Compose — Multi-container orchestration
- Nginx — Serves frontend, proxies
/apito backend
- Docker and Docker Compose
-
Clone the repository
git clone <repo-url> cd kuberone
-
Configure environment variables
cp .env.example .env
Open
.envand set:Variable Description DB_PASSWORDPostgreSQL password SECRET_KEYJWT signing key (at least 32 random characters) FRONTEND_URLFrontend origin for CORS (default: http://localhost:5173) -
Start the application
docker-compose up -d
-
Open your browser: http://localhost:5173
-
Register — creates your family account (you become Admin). Log in and start adding accounts and holdings.
The first user to register creates a Family and becomes its Admin. The admin can invite members via Settings → Members (generates an activation link). Invited members set their own password before logging in.
Each family member can have multiple investment accounts (e.g., "HDFC Demat", "Zerodha", "US Brokerage"). Accounts specify a currency and can be reordered on the Accounts page.
Add holdings manually by entering a ticker symbol. Prices are fetched from Yahoo Finance.
| Market | Symbol format | Example |
|---|---|---|
| Indian stocks (NSE) | SYMBOL.NS |
RELIANCE.NS, TCS.NS |
| Indian stocks (BSE) | SYMBOL.BO |
RELIANCE.BO |
| US stocks | Plain symbol | AAPL, GOOGL |
| Other markets | Check Yahoo Finance | — |
Holdings can also be bulk-imported via CSV or Excel from the Holdings page.
Aggregates all holdings across all accounts and shows:
- Summary tiles: Total Investment, Current Value, Total P&L, Total Return %
- Performance trendline over time
- Top 5 Lifetime Gainers / Losers
- Top 5 Daily Gainers / Losers
Go to Settings → Backup to export all accounts and holdings to a .json file. Admins can choose which family members to include; members export only their own data.
To restore, upload a KuberOne backup file. Two modes are available:
- Clear & Restore — wipes existing holdings in matched accounts before importing (best for a clean restore)
- Append — adds backup holdings alongside existing ones
Accounts are matched by name + currency + owner. New accounts are created if no match is found; existing accounts are never duplicated.
# Start all services
docker-compose up -d
# Stop services (keep data)
docker-compose down
# Stop and remove volumes (deletes database)
docker-compose down -v
# Rebuild after code changes
docker-compose up -d --build
# View logs
docker-compose logs -f
docker-compose logs -f backend
docker-compose logs -f frontend- Passwords hashed with bcrypt (12 rounds)
- JWT access tokens (short-lived) + refresh tokens with JTI rotation
token_versionon User enables instant invalidation of all sessions- CORS restricted to configured
FRONTEND_URL - All secrets via environment variables — nothing hardcoded
Database connection failed
docker-compose ps # Check all containers are running
docker-compose logs db # Check PostgreSQL logsPort 5173 already in use
Change the host port in docker-compose.yml:
ports:
- "3000:5173" # Access on http://localhost:3000Also update FRONTEND_URL in .env to match.
Symbol not found / price shows zero
- For Indian NSE stocks append
.NS(e.g.,RELIANCE.NS) - For BSE stocks append
.BO - Verify the symbol at finance.yahoo.com
Frontend shows blank page
docker-compose logs frontend
docker-compose up -d --build frontendMIT License — feel free to use and modify.