PFM — Personal Finance Manager
A self-hosted personal finance web application. Track income, expenses, investments, budgets, and savings goals. AI-powered financial assistant and receipt OCR built in. Sync bank accounts via Teller or Schwab.
Live at: https://pfm.ngodanguyen.tech
Table of Contents
- Features Overview
- Getting Started
- Dashboard
- Transactions
- Accounts
- Categories
- Budgets
- Goals & Savings
- Investments
- AI Assistant
- Reports & Export
- Settings
- Recurring Transactions
- CSV Import
- Receipt OCR
- Teller Bank Sync
- Schwab Bank Sync
- USD → VND Rate Widget
- Keyboard Shortcuts & Tips
Features Overview
| Module | What it does |
|---|---|
| Dashboard | Net worth, cash flow chart, budget gauges, AI insight, USD/VND rate |
| Transactions | Income + expense entry, transfer, filter, search, inline category change, receipt upload |
| Accounts | Multiple bank/cash/credit accounts, auto-calculated or provider-synced balances |
| Categories | Custom expense + income categories with color and icon |
| Budgets | Monthly spending limits per category with progress tracking |
| Goals | Savings goals with contribution tracking and projected completion |
| Investments | Stock/ETF/crypto/real estate portfolio, per-account view (Individual vs Roth IRA), live price fetch |
| AI Assistant | Chat with your finances via Groq (free), daily auto-insight |
| Receipt OCR | Drag-drop a receipt image — AI extracts and fills the form |
| Reports | Monthly/quarterly/yearly summaries, net worth history, PDF/CSV/Excel export |
| Teller | Live US bank account sync (mTLS), balance refresh, transaction import |
| Schwab | Schwab brokerage sync — balance, stock/ETF positions, transaction import |
| Settings | Profile, currency, recurring rules, CSV import, password |
Getting Started
First Login
- Navigate to
https://pfm.ngodanguyen.tech - Enter the username and password created during setup (
python scripts/init_db.py) - Check "Remember me" to stay logged in across browser sessions
Recommended Setup Order
- Add accounts — add your bank accounts, cash wallet, and credit cards first
- Review categories — default categories are already seeded; add custom ones if needed
- Set your currency — go to Settings → Profile and set your app currency
- Connect bank sync — connect Teller (US banks) or Schwab for automatic data
- Add transactions — start entering income and expenses (or import via bank sync)
- Set budgets — once you have categories, set monthly limits
- Create goals — add savings goals and start contributing
- Add investments — manually or via Schwab sync
Dashboard
The dashboard is the home screen — accessible from the sidebar or by clicking the PFM logo.
Period Selector
Three buttons in the top-right: This Month, Last Month, Custom (date range picker).
Summary Cards
- Income — total income for the selected period
- Expenses — total expenses for the selected period
- Net Cash Flow — income minus expenses
- Net Worth — total assets minus liabilities across all accounts
Cash Flow Chart
Bar chart showing the last 6 months of income (green) vs expenses (red).
Accounts Panel
Lists all active accounts with current balances. Credit cards show the Amount Owed (positive number) instead of a raw negative balance. Green = positive balance, red = amount owed.
AI Daily Insight
Auto-generated summary of your finances. Click "Open AI →" for the full chat interface.
USD → VND Widget
Reference-only exchange rate. Click ↻ to refresh. Click the widget to show a 30-day chart.
Transactions
Viewing Transactions
Navigate via Transactions in the sidebar. Two tabs: Expenses and Income.
Filtering
Search bar, category dropdown, account dropdown, date range. Click ✕ to clear all filters.
Adding a Transaction
Use the sidebar links (Add Income / Add Expense), the dashboard quick-add buttons, or the topbar buttons on the transaction list.
Inline Category Change
On any transaction row, click the category dropdown directly in the table to change the category without opening the edit form. The change saves automatically.
Editing and Deleting
Click Edit to open the full form (same as adding, plus receipt management). Click Del to delete permanently.
Transfers
Click Transfer in the topbar. Creates a single transfer between two accounts. Transfers are excluded from income/expense totals.
Accounts
Account Types
checking / savings / cash / credit_card / crypto / investment / other
Balance Sources
- Manually managed accounts — balance is computed from all transactions (income − expenses − transfers out + transfers in). Updates automatically after every transaction.
- Teller-linked accounts — balance comes from Teller's live API. Shown with a blue Teller badge. Use the action buttons on the account card.
- Schwab-linked accounts — balance comes from Schwab's snapshot sync. Shown with a green Schwab badge. Use the action buttons on the account card.
Teller Account Actions (on account card)
| Button | What it does |
|---|---|
| Refresh | Pulls the live balance from Teller API (AJAX, no page reload) |
| Sync | Opens transaction preview — import new transactions from this account |
| Reset | Clears the sync cursor — next Sync will re-fetch the full 90-day history |
Schwab Account Actions (on account card)
| Button | What it does |
|---|---|
| Balance & Positions | Fetches live balance + investment holdings from Schwab, updates immediately |
| Transactions | Opens transaction import preview for this account |
Credit Cards
Credit cards show two values:
- Amount Owed — how much you currently owe (positive number in red)
- This Month — expenses charged to the card this calendar month
Opening Balance
When creating a new account, enter the current balance in the Opening Balance field. For credit cards, enter a negative number to indicate debt (e.g. -500 if you owe $500).
Categories
Navigate via the sidebar footer → Categories.
Default Expense (14): Housing, Food & Dining, Transport, Utilities, Health, Entertainment, Shopping, Education, Insurance, Personal Care, Travel, Subscriptions, Gifts, Other
Default Income (7): Salary, Freelance, Business, Investment, Rental, Gift Received, Other Income
System categories (grey badge) cannot be deleted but color/icon can be changed. Custom categories can be fully edited and deleted.
Budgets
Navigate via Budgets in the sidebar. Use ◀ ▶ to navigate months.
- Set monthly limits per expense category
- Progress bars: green (< 80%) → amber (80–99%) → red (100%+)
- Rollover toggle: unspent budget carries forward to next month
- Copy from previous month — duplicate last month's budgets in one click
Goals & Savings
Navigate via Goals in the sidebar.
- Create goals with target amount, target date, color, and icon
- Add contributions with dates and notes
- Auto-completes when target is reached
- Emergency Fund Tracker — shows how many months your liquid assets cover at current spending
Investments
Navigate via Investments in the sidebar.
Portfolio Overview
Summary cards: Total Value, Total Cost, Unrealized P&L, Return %. Allocation doughnut chart by asset type.
Per-Account View
If you have investments in multiple accounts (e.g. Schwab Individual + Schwab Roth IRA), the holdings are displayed in separate sections, one per account. Each section shows the account name, total account value, and the holdings table for that account. The allocation chart sidebar also shows a "By Account" balance breakdown.
Syncing from Schwab
Click Sync Schwab in the topbar to pull the latest holdings and balances for all mapped Schwab accounts. After syncing, each holding is associated with its source account so Individual and Roth IRA positions stay separate even if they hold the same tickers.
Adding a Holding Manually
Click Add Holding in the topbar. After saving, go to the detail page to record buy transactions.
Ticker Format
- US Stocks:
AAPL,MSFT - ETFs:
VOO,QQQ - Crypto:
BTC-USD,ETH-USD - Other markets: Yahoo Finance suffix (e.g.
VIC.VN)
Refreshing Prices
Click Refresh Prices in the topbar. Prices also auto-update daily at 4PM (weekdays).
AI Assistant
Navigate via AI Assistant in the sidebar.
The AI has access to the last 90 days of transactions, budget status, goals, investments, and net worth. No personal names or identifying details are sent to Groq — only aggregated financial figures.
- Type and press Enter to send; Shift+Enter for new line
- Eight quick-question suggestion buttons on the right
- Daily Insight — auto-generated summary at midnight; click Generate Now to create on demand
- Chat History button — all past responses with timestamps
AI Model
Change in Settings → Profile → AI Model: llama-3.3-70b-versatile (best quality) or llama-3.1-8b-instant (faster).
Reports & Export
Navigate via Reports in the sidebar.
Four tabs: Monthly, Quarterly, Yearly, Tax Year.
Export buttons in the topbar: CSV (plain text), Excel (color-coded, formatted), PDF (printable report).
Snapshot Now — saves today's net worth to the history chart.
Settings
Navigate via the gear icon at the bottom of the sidebar.
| Section | What you can change |
|---|---|
| Profile | Display name, email, timezone, currency, AI model |
| Password | Current password + new password (min 6 chars) |
| Recurring | Create/edit/pause recurring transaction rules |
| Import | Upload CSV to bulk-import transactions |
Recurring Transactions
Navigate via Settings → Recurring.
Rules auto-create transactions on a schedule. Frequencies: daily, weekly, biweekly, monthly, quarterly, yearly. Run Now button processes all overdue rules immediately.
CSV Import
Navigate via Settings → Import.
Required columns: date, type (income/expense), description, amount
Optional: category, account, notes
Process: upload → preview (with warnings for unmatched categories/accounts) → confirm.
Receipt OCR
On the new expense form: drag-drop or click the purple panel to upload a receipt image (JPG/PNG/GIF/WEBP, max 10MB). The AI extracts amount, date, merchant, and category and fills the form. Always review before saving.
On the edit form: click Re-extract to re-run OCR on an already-attached receipt.
Teller Bank Sync
Teller connects US bank accounts using a secure mTLS connection.
Connecting
- Go to Bank Connections in the sidebar
- Click Connect a Bank — the Teller Connect modal opens
- Select your bank and log in
- After connecting, go to the Map Accounts page to link each Teller account to a PFM account
Syncing Transactions
On the Accounts page, find your Teller-linked account (blue Teller badge) and click Sync. Review the transaction preview and confirm to import.
Refreshing Balance
Click Refresh on a Teller account card to pull the live balance from your bank. For checking/savings this shows the available balance; for credit cards it shows the amount owed.
Disconnecting
Go to Bank Connections → Disconnect next to the institution. Imported transactions are kept.
Schwab Bank Sync
Schwab integration uses OAuth 2.0 to sync brokerage and IRA accounts.
Connecting
- Set
SCHWAB_CLIENT_ID,SCHWAB_CLIENT_SECRET,SCHWAB_REDIRECT_URIin.env - Register the redirect URI in the Schwab developer portal
- Go to Schwab in the sidebar → Connect Schwab Account
- Authorize on Schwab's login page
- On the Map Accounts page, link each Schwab account to a PFM account (or create new ones)
Syncing Balance & Investment Positions
On the Accounts page, find your Schwab-linked account (green Schwab badge) and click Balance & Positions. This:
- Updates the account's balance to Schwab's total portfolio value
- Imports all stock/ETF/bond/fund holdings into the Investments section
- Associates each holding with the specific account (Individual vs Roth IRA stay separate)
You can also click Sync Schwab in the Investments page topbar to update all Schwab accounts at once.
Syncing Transactions
Click Transactions on a Schwab account card. Review the preview and confirm to import.
Per-Account Investment View
After syncing both Individual and Roth IRA accounts, the Investments page shows separate sections for each account — even if both hold the same ticker (e.g. AAPL appears in both sections independently).
Disconnecting
Go to Schwab in the sidebar → Disconnect. Imported transactions and investment holdings are kept.
USD → VND Rate Widget
Reference-only exchange rate on the dashboard. Does not affect any app calculations.
- Click ↻ to force-refresh without reloading the page
- Click the widget to show a 30-day trend chart
- ⚠ indicator appears if the cached rate is more than a day old
Keyboard Shortcuts & Tips
Navigation
- Sidebar collapses on desktop — click ☰ to toggle (state remembered)
- On mobile, tap outside the sidebar to close it
Transactions
- Enter sends in AI chat; Shift+Enter adds a new line
- Change category directly in the transactions table — click the category dropdown on any row
- Date defaults to today; change it for past transactions
Investments
- Click any row in the holdings table to go to the detail page
- ↓ button on the transaction price field fetches the current live price
- Ticker symbols are auto-uppercased on save
- Sync Schwab (topbar) syncs all Schwab accounts at once
Budgets
- Copy from previous month button at the start of each month saves re-entering all budgets
- Rollover amounts appear as a blue "+rollover" badge
Reports
- Snapshot Now button saves today's net worth to the history chart
- CSV/Excel exports use the period currently selected in the report view