A self-hosted investment tracking platform for managing portfolios, analyzing performance, and tracking financial goals.
Disclaimer: This is a personal vibe-coded project and my second public attempt at vibe coding. The current implementation may not reflect best practices in architecture or code design, that's intentional for now. A refactor is planned in the coming weeks to address that, given that my intentions for this project is to make use of it as my own portfolio tracking tool.
Portfolio Management
- Multi-portfolio support with trade history (buy, sell, dividend, fee)
- Holdings tracking with live market data via yfinance
- Asset classes: stocks, ETFs, crypto, and cash
- CSV import with column mapping, validation, and error reporting
- Multi-currency support with automatic FX conversion
Analytics
- Time-weighted return (TWR) and money-weighted return (MWR)
- Asset allocation breakdown by class and sector
- Portfolio performance history and contribution charts
Goal Tracking
- Financial goals with target dates and expected return inputs
- FIRE projection calculations
- Visual progress tracking
| Layer | Technology |
|---|---|
| Frontend | SvelteKit, TypeScript, Tailwind, shadcn-svelte, bits-ui |
| Backend | FastAPI, SQLAlchemy (async) |
| Database | PostgreSQL |
| Data | yfinance |
| Infra | Docker, Docker Compose |
Requirements: Docker and Docker Compose.
git clone https://github.com/aybruhm/folio.git
cd folio
make setupIf you just want to run Folio locally for personal use, pull the pre-built images from GHCR and start the stack.
First-time setup — create your environment files from the provided examples:
make prod-setupOpen api/.env.prod and web/.env.local and fill in your values (database credentials, API URL, etc.), then:
make prod-pull
make prod-up
make prod-migrateOptionally seed the database with a demo portfolio (stocks, crypto, and cash positions):
make prod-seedOnce running:
| Service | URL |
|---|---|
| Frontend | http://localhost:3000 |
| API | http://localhost:8000 |
| API Docs | http://localhost:8000/docs |
If you want to contribute or run the app with hot reload, use the dev stack instead. This builds images locally from source:
make up
make db-migrateOptionally seed demo data:
make db-seed| Command | Description |
|---|---|
make prod-setup |
Create production .env files from examples |
make prod-up |
Start production services |
make prod-down |
Stop production services |
make prod-restart |
Restart production services |
make prod-logs |
Stream production logs |
make prod-migrate |
Run database migrations in production |
make prod-seed |
Seed production database with demo data |
make prod-health |
Check production service health |
make prod-pull |
Pull latest images from GHCR |
| Command | Description |
|---|---|
make setup |
Create .env files from examples |
make up |
Start all services |
make down |
Stop all services |
make restart |
Restart all services |
make logs |
Stream logs from all services |
make health |
Check service health status |
make clean |
Remove containers and prune system |
| Command | Description |
|---|---|
make db-migrate |
Run pending Alembic migrations |
make db-seed |
Seed demo portfolio data |
make db-reset |
Drop and recreate schema |
make db-shell |
Open PostgreSQL shell |
| Command | Description |
|---|---|
make api-shell |
Shell into the API container |
make api-lint |
Lint Python code |
make api-format |
Format with black and isort |
make api-test |
Run API tests |
make web-shell |
Shell into the web container |
make web-lint |
Lint TypeScript/Svelte code |
make web-build |
Build the production frontend |
- Authentication: JWT-based auth with HTTP-only cookies to secure the API and frontend
- (Backend) Testing: It's imperative that we do this before we begin refactoring
- Refactor: improve code patterns, architecture, and design decisions across the stack

