ledgerly is an offline-first SwiftUI personal finance app that keeps data on-device while providing wallets, transactions, budgets, goals, manual assets, liabilities, and investment tracking. Reports normalize to a base currency with manual exchange rates, and optional live price refresh for crypto and stocks.
Read CONTRIBUTING.md for collaboration guidelines, coding standards, and the review checklist.
- Offline-first Core Data storage with manual JSON backup and restore.
- Customizable dashboard with reorderable widgets for net worth, financial health, expense mix, spending cadence, and income progress.
- Multi-currency wallets with base-currency reporting and manual FX overrides.
- Fast transaction capture with transfers, categories, filters, and a detail editor built for quick edits.
- Manual entries for assets, receivables, investments, and liabilities with wallet funding and profit tracking.
- Budget alerts and goal reminders driven by system notifications.
- Architecture
- Feature Tour
- Currency & Exchange Rates
- Running the App
- Data Model Snapshot
- Extending ledgerly
- Screenshots
ledgerly follows a layered SwiftUI architecture centered around Core Data and observable stores.
ledgerlyApp.swiftwires shared stores (AppSettingsStore,WalletsStore, etc.) asEnvironmentObjects.ContentViewswitches between the multi-step onboarding flow and the main tab UI.- The tab bar hosts
HomeOverviewView,WalletsView,TransactionsView, andMoreHubView. - Swift Charts powers the expense donut and income progress charts.
PersistenceControllerowns the Core Data stack and background contexts.- Store objects inside
ledgerly/Datamap Core Data entities into@Publishedmodels and handle background writes. - Wallet updates broadcast through
NotificationCenterso net worth and dashboards refresh automatically.
NetWorthServicecalculates totals, monthly snapshots, FX exposure, and manual investment performance.ManualInvestmentPriceServicerefreshes crypto prices via CoinGecko and stock quotes via Alpha Vantage.BudgetAlertServiceandGoalReminderServiceschedule notification alerts.DataBackupServiceexports and imports full JSON backups.
- Everything is stored locally in Core Data; no network is required for core tracking flows.
- FX rates are manual; when a rate is missing, amounts stay in their native currency.
- Live prices and ticker search are optional and only used when API keys are configured.
- Backups are manual JSON exports through the system share sheet.
- Four steps: Welcome, Base Currency, Exchange Mode, Summary.
- Exchange mode is stored as a preference and can be adjusted later in Settings.
- Card-based dashboard with reorderable widgets managed in Dashboard Preferences.
- Net Worth Breakdown: donut segments for wallets, tangible assets, receivables, investments, and liabilities plus delta vs last snapshot.
- Financial Health: 7D/30D/90D cash flow, liquidity share and ratio, investment profit, and FX exposure with commentary.
- Expense Breakdown: category donut with 7D/30D/90D ranges and change badges.
- Spending Cadence: Today/This Week/This Month tiles with delta badges that link to filtered transactions.
- Income Progress: yearly bar chart with month selection and previous-year navigation.
- Budget and Goals summaries surface the top 3 items, and a toolbar action opens manual entries or refreshes prices.
- Wallets are grouped into Income Sources and Accounts based on wallet kind.
- Add and edit flows include name, type, currency, balances, net worth inclusion, and an icon picker.
- Swipe to delete or tap to edit details.
- Summary tiles highlight this month, last month, income, and expense totals in the base currency.
- Segmented control switches between all, expenses, income, and transfers; filters include wallet, date range, and notes or wallet search.
- Entries are grouped by day with per-day totals; rows show base amounts plus native amounts when currencies differ.
- Creation form supports transfers, category creation, currency selection, and notes.
- Detail view uses expandable sections with per-field Save/Reset plus a "Zen Edit" mode to keep all editors open.
- Monthly budgets by category with limit amounts and month/year selection.
- Detail view shows spend vs limit with progress bars.
- Alerts fire at 50/80/100 percent when notifications are enabled.
- Overview card summarizes active vs completed, average progress, and the next deadline.
- Filter active/completed/all goals with progress bars and due-date labels.
- Detail view shows progress, remaining amount, monthly target math, and timeline.
- Contributions support add or withdraw, and goals can link to wallets and categories for auto-updates.
- Separate sections for assets, receivables, investments, and liabilities with sheet-based add/edit.
- Investment form supports crypto or stock, ticker search suggestions, contract multipliers, and a funding wallet that adjusts balances.
- Holdings show cost basis, profit/loss, and original currency values when converted.
- Price refresh pulls CoinGecko for crypto (optional API key) and Alpha Vantage for stocks (requires key).
- Base currency, exchange mode, notifications, and manual FX rates in "Dashboard & Settings".
- Dashboard preferences for reordering or hiding widgets.
- JSON backup export/import plus a net worth rebuild option (recalculates from Jan 2026 using current rates).
- The base currency drives dashboards, summaries, and net worth totals.
- Each wallet keeps its own currency; conversions pass through the base currency via
CurrencyConverter. - Exchange mode (official/parallel/manual) is stored as a preference; manual rates are editable per currency.
- Missing rates fall back to the original amount rather than blocking calculations.
- Transactions store both native amounts and base conversions for reproducible reports.
- Requirements: Xcode 15.4 or newer, iOS 17 simulator or device, Swift 5.9 toolchain.
git clonethis repository and openledgerly.xcodeprojin Xcode.- Select the
ledgerlyscheme and your preferred simulator (the sample screenshots use iPhone 16 Pro Max). - Build and run. The onboarding flow guides you through base currency and exchange mode selection before showing the dashboard.
- Optional keys (set in the scheme environment):
COINGECKO_API_KEYfor higher CoinGecko rate limits.ALPHAVANTAGE_API_KEYfor stock price refresh.MASSIVE_API_KEYfor stock ticker search suggestions.
- If Core Data migrations fail, delete the app from the simulator and rerun.
- Importing a backup replaces wallets, budgets, goals, and manual entries; stores reload automatically.
| Domain | Entities / Models | Notes |
|---|---|---|
| Configuration | AppSettings |
Base currency, exchange mode, notifications, dashboard order, manual FX rates. |
| Wallets & Categories | Wallet, Category |
Wallet types, balances, icons, and income/expense categories. |
| Transactions | Transaction |
Unified ledger with transfers, base conversions, and notes. |
| Budgets | MonthlyBudget, BudgetAlert |
Monthly limits with notification thresholds. |
| Goals | SavingGoal |
Targets, deadlines, status, wallet/category links. |
| Manual Entries | ManualAsset, ManualLiability |
Assets, receivables, investments, and liabilities. |
| Net Worth | NetWorthSnapshot |
Monthly aggregates and notes. |
| Investments (future) | InvestmentAccount, InvestmentAsset, HoldingLot, HoldingSale, PriceSnapshot |
Model scaffolding not yet surfaced in the UI. |
| Misc | Item |
Template stub, unused in the app. |
- Plug in new market data providers by adapting
ManualInvestmentPriceServiceorMarketDataClient. - Add CSV exports using
DataExportServiceor surface it in Settings. - Enable CloudKit by swapping
PersistenceControllertoNSPersistentCloudKitContainer. - Build widgets or App Intents on top of
NetWorthStoreandTransactionsStore.
Yohannes Haile, 2026