New
Apps 987Makers 986This week 987
Promote your app−30%
Wealthfolio screenshot 1
0views in
the last 30 days

Wealthfolio

Open-source, private portfolio tracker for investments, net worth and spending.

Built with Claude Code

by wealthfolio · from CACanada · added Oct 29, 2026
no ratings0 comments
Logo

Wealthfolio

The open-source, private portfolio tracker — investments, net worth, spending, and simulations.
Local-first: your data lives on your device.

Website · Discord · Twitter · Releases

⬇️  Download for macOS · Windows · Linux  ·  📱 iOS App  ·  🐳 Docker

Buy me a coffee button

Introduction

Wealthfolio is an open-source, private portfolio tracker — investments, net worth, spending, and simulations. All your data is stored locally on your device: no cloud database, no account required, free forever.

For automatic brokerage syncing (30+ institutions, read-only) and encrypted multi-device sync, there's Wealthfolio Connect — an optional subscription that covers the real cost of the brokerage data connections. The app never requires it: manual tracking and CSV import are free, forever.

Visit the website at wealthfolio.app.

Screenshot

✨ Key Features

  • 📊 Portfolio Tracking - Track your investments across multiple accounts and asset types
  • 📈 Performance Analytics - True time-weighted and money-weighted returns, benchmark comparison, and historical analysis
  • 💰 Activity Management - Import and manage all your trading activities
  • 🎯 Goal Planning - Set and track financial goals with allocation management
  • 🔒 Local Data - All data stored locally with no cloud dependencies
  • 🔄 Optional Broker Sync - Auto-sync 30+ brokerages with Wealthfolio Connect (read-only, entirely optional)
  • 🧩 Extensible - Powerful addon system for custom functionality
  • 🌍 Multi-Currency - Support for multiple currencies with exchange rate management
  • 📱 Cross-Platform - Desktop (Windows, macOS, Linux), iOS, and self-hosted Docker/web

Wealthfolio 3.7 requires macOS 12 or newer and iOS/iPadOS 16 or newer. macOS 12 installations should apply current macOS and Safari updates so the system WKWebView meets the Safari 16 browser floor. Windows uses the evergreen WebView2 runtime; Linux and self-hosted installations should keep WebKitGTK or their browser updated.

🧩 Addon System

Wealthfolio features a powerful addon system that allows developers to extend functionality:

  • 🔌 Easy Development - TypeScript SDK with full type safety and hot reload
  • 🔒 Secure - Comprehensive permission system with user consent
  • ⚡ High Performance - Optimized for speed with minimal overhead
  • 🎨 UI Integration - Add custom pages, navigation items, and components
  • 📡 Real-time Events - Listen to portfolio updates, market sync, and user actions
  • 🗄️ Full Data Access - Access to accounts, holdings, activities, and market data
  • 🔐 Secrets Management - Secure storage for API keys and sensitive data
  • 📦 Private Assets - Package images, fonts, media, configuration, and Wasm for the isolated addon sandbox

Get started building addons: See the Addon Documentation Hub

Documentation for all Activity types, including the required form fields, is available in docs/activities/activity-types.md.

Roadmap

See ROADMAP.md.

📖 Documentation

Core Application

  • Activity Types - Complete guide to all supported activity types and their required fields
  • Roadmap - Future plans and development roadmap

Architecture

  • Credential Storage - Native backends, server encryption, Android backup, and recovery
  • Android Testing - Setup, emulator/device commands, APK builds, and smoke tests
  • Adapter System - Compile-time environment detection for Desktop/Web builds

Addon Development

Quick Links

Getting Started

Prerequisites

Ensure you have the following installed on your machine:

Building from Source

  1. Clone the repository:

    git clone https://github.com/wealthfolio/wealthfolio.git
    cd wealthfolio
    
  2. Install dependencies using pnpm:

    pnpm install --frozen-lockfile
    pnpm build:types
    

    See Frontend tooling for editor setup, checks, and instructions for updating an existing checkout.

  3. Setup environment configuration:

    Copy the environment template and configure it for your setup:

    cp .env.example .env
    

    For optional Connect setup, see Wealthfolio Connect in source builds.

    Desktop development uses a separate application identity and profile directory. On macOS, the default layout is:

    ~/Library/Application Support/com.teymz.wealthfolio.dev/
    ├── profiles.json
    └── profiles/<uuid>/app.db
    

    To select another profile directory during desktop development, set WF_DATA_DIR in .env to an absolute path as described in .env.example. Leave it unset to use the default development app-data directory. Use a dedicated development directory; this setting selects the registry and its profiles, not an individual database file. An existing root-level app.db is only adopted on first profile initialization.

    If your older .env contains DATABASE_URL, remove it: pnpm tauri dev ignores it, including on first launch. Use WF_DATA_DIR for development directory selection. Packaged desktop apps do not ship with an .env file.

  4. Run in Development Mode:

pnpm tauri dev

The command automatically applies apps/tauri/tauri.dev.conf.json, which sets com.teymz.wealthfolio.dev and Wealthfolio (Development). This identity remains in effect when additional --config overrides are supplied, including when running pnpm tauri dev --release. Production builds (pnpm tauri build) retain the production identity. For an isolated packaged debug build, select the same configuration explicitly:

pnpm tauri build --debug --config apps/tauri/tauri.dev.conf.json

Credentials follow the selected application identity, not debug/release mode. Production Keychain names are unchanged. Development has separate credentials, so sign in and enroll it as a separate sync device if needed; later development runs reuse those credentials. Profiles and add-ons retain their existing scopes within each environment. Mobile commands retain their configured identity.

To populate development with existing data, use the supported backup/export and restore flow. A raw copy of an encrypted production database still requires its original encryption key; development does not copy or fall back to production credentials. Never point development at the live production profile directory.

Packaging for a Distribution

If a package manager delivers updates, set WEALTHFOLIO_UPDATE_EXPLANATION to the message users should see when building:

WEALTHFOLIO_UPDATE_EXPLANATION="Update Wealthfolio with your package manager." pnpm tauri build

The desktop app still announces new releases with their notes, but shows this message instead of an Update Now button and refuses to install updates itself. A launcher script can set the same variable at run time instead. Flatpak installs, and .deb/.rpm builds whose binary dpkg or rpm did not install, are detected without it.

Addon Development Mode

Addon hot reload servers now start only when you explicitly opt in.

For desktop development with Tauri:

VITE_ENABLE_ADDON_DEV_MODE=true pnpm tauri dev

For browser-only development (Vite only, no Tauri):

pnpm dev:addons

You can also set VITE_ENABLE_ADDON_DEV_MODE=true in your .env file to persist the setting.

  1. Build for Production:

Build the application for production:

pnpm tauri build

Web Mode (Browser + REST API server)

Run the web UI with a local Axum server with one command.

Quick Start

  1. Setup environment (optional but recommended):

    Copy the example environment file and customize it for your setup:

    cp .env.web.example .env.web
    

    Edit .env.web to configure database path, ports, and other settings as needed.

  2. Start both backend and Vite dev server:

    pnpm run dev:web
    

    The Vite dev server runs at http://localhost:1420 and proxies API calls to the Axum backend server.

Configuration

All configuration is done via environment variables in .env.web.

Server Configuration (WF_* variables):

  • WF_LISTEN_ADDR - Server bind address (default: 0.0.0.0:8088)
  • WF_DATA_DIR - Optional directory for the profile registry, profile databases, and default encrypted vault. For pnpm dev:web, set it in .env.web or the shell; the desktop .env value is masked. Relative paths use the working directory; ~ is not expanded.
  • WF_DB_PATH - Supported legacy database file path (default: ./db/app.db). Its parent selects the installation when WF_DATA_DIR is unset. With only WF_DATA_DIR, the legacy candidate is <WF_DATA_DIR>/app.db. If both are set, their directories must agree. Existing registries retain their saved database paths; neither setting moves data. See installation directory configuration for Docker and upgrade behavior.
  • WF_CORS_ALLOW_ORIGINS - Comma-separated list of allowed CORS origins (default: *). Required when auth is enabled — wildcard * is rejected.
    • Example: https://wealthfolio.example.com
  • WF_REQUEST_TIMEOUT_MS - Request timeout in milliseconds (default: 300000)
  • WF_STATIC_DIR - Directory for serving static frontend assets (default: dist)
  • WF_SECRET_KEY - 32-byte key used for secrets encryption and JWT signing (required unless WF_SECRET_KEY_FILE is set)
    • Generate with: openssl rand -base64 32
  • WF_SECRET_KEY_FILE - Optional master-key file; see setup and mount instructions
  • WF_AUTH_PASSWORD_HASH - Argon2id PHC string enabling password-only authentication for web mode
  • WF_AUTH_TOKEN_TTL_MINUTES - Optional JWT access token expiry in minutes (default 60)
  • WF_AUTH_REQUIRED - Set to false to allow starting on non-loopback addresses without authentication (e.g. when a reverse proxy handles auth)
  • OIDC / SSO (optional) - sign in via any OpenID Connect provider (Authentik, PocketID, Authelia, Keycloak, …). Works alongside or instead of WF_AUTH_PASSWORD_HASH; a successful SSO login mints the same session cookie. Enabled when both WF_OIDC_ISSUER_URL and WF_OIDC_CLIENT_ID are set.
    • WF_OIDC_ISSUER_URL - provider base URL (discovery hits <issuer>/.well-known/openid-configuration)
    • WF_OIDC_CLIENT_ID - client id registered with the IdP
    • WF_OIDC_CLIENT_SECRET - Optional client secret (PKCE is always used)
    • WF_OIDC_REDIRECT_URL - Required when OIDC is enabled; must be registered in the IdP, e.g. https://your.host/api/v1/auth/oidc/callback
    • WF_OIDC_SCOPES - Optional space-separated scopes (default openid email profile)
    • WF_OIDC_ALLOWED_EMAILS / WF_OIDC_ALLOWED_SUBS - comma-separated allowlists matched against the ID token's email / sub claims. With neither set, the server refuses to start unless WF_OIDC_ALLOW_ANY=true is also set — a missing allowlist must never silently grant every IdP user access. An email is only honored when the IdP asserts email_verified=true; WF_OIDC_ALLOWED_SUBS is the stronger control (stable, issuer-scoped) and is recommended on shared/multi-tenant IdPs.
    • WF_OIDC_ALLOW_ANY - Optional, default false. Set to true to allow any user the IdP authenticates when no allowlist is configured. Only safe on a dedicated single-user IdP; on a shared/multi-tenant IdP this grants everyone access. A warning is logged at startup when enabled.
    • WF_OIDC_POST_LOGOUT_REDIRECT_URL - Optional. When the IdP advertises an end_session_endpoint, sign-out also ends the IdP session (RP-Initiated Logout); otherwise logout is local-only. Set this to land back on the app afterward — it must be registered with the IdP (e.g. Keycloak's "Valid post logout redirect URIs"). If unset, the IdP shows its own logged-out page.
    • WF_OIDC_RP_LOGOUT - Optional, default true. Set to false to force local-only logout even when the IdP supports RP-Initiated Logout.
    • WF_OIDC_CA_FILE - Optional path to a PEM bundle of extra root certificates trusted for OIDC requests only (discovery, token exchange). Use it when the IdP's certificate comes from a private CA (e.g. step-ca); the OIDC client otherwise trusts only the bundled Mozilla roots and ignores the system store and SSL_CERT_FILE. The bundled roots stay trusted. The server refuses to start if the file is unreadable or holds no certificate.
  • WF_COOKIE_SECURE - Controls the Secure attribute on session cookies (default: auto)
    • auto - set Secure only when X-Forwarded-Proto: https is present (recommended for most reverse-proxy setups)
    • true - always set Secure (use when TLS is guaranteed but the header is absent)
    • false - never set Secure (plain HTTP without a reverse proxy)
  • WF_SECRET_FILE - Optional path to secrets storage file (default: <data-root>/secrets.json)
  • WF_ADDONS_DIR - Optional path to addons directory (default: derived from database path)

Vite Configuration:

  • VITE_API_TARGET - Backend API URL for Vite proxy (default: http://127.0.0.1:8088)

Authentication (Web Mode)

  • Set WF_AUTH_PASSWORD_HASH to an Argon2id PHC string to require a password before accessing the Web App.

    You can generate the hash with online tools like argon2.online or the CLI (argon2-utils package):

    printf 'your-password' | argon2 yoursalt16chars! -id -e
    

    Tips:

    • The first argument is the salt (use 16+ characters); the password is read from stdin.
    • Use printf instead of echo -n to avoid hidden newline issues.
    • For Docker Compose .env / --env-file, single-quote the hash or double every $ ($$argon2id$$...).

    Copy the full output (starting with $argon2id$...) into .env.web.

    Dollar-sign ($) escaping cheat-sheet — Argon2 hashes contain $ characters that shells and Compose interpret as variable references:

    Context Syntax Notes
    .env.web / app-loaded dotenv WF_AUTH_PASSWORD_HASH=$argon2id$... Loaded by the app; no Compose interpolation
    Docker Compose .env/--env-file WF_AUTH_PASSWORD_HASH='$argon2id$...' Single quotes prevent Compose interpolation
    Docker Compose .env/--env-file `WF_AUTH_PASSWORD_HASH=$$arg

Description taken from the repository README.

Ratings

–
0 ratings
5 0
4 0
3 0
2 0
1 0

Rate this app

Sign in to rate

Comments 0

Sign in to comment

No comments yet.

Related apps

#finance · #investing · #desktop