# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Portfolio Journal is a native iOS investment portfolio tracker built with Swift and SwiftUI. It helps users track investments, monitor performance with charts and predictions, set financial goals, and maintain an investment journal. **Target:** iOS 17.6+ (widget supports iOS 16.0+) ## Build Commands ```bash # Open project in Xcode open PortfolioJournal.xcodeproj # Build for Debug xcodebuild -scheme PortfolioJournal -configuration Debug build # Build for Release xcodebuild -scheme PortfolioJournal -configuration Release build # Run on simulator xcodebuild -scheme PortfolioJournal -configuration Debug -destination 'platform=iOS Simulator,name=iPhone 15' build # Clean build xcodebuild -scheme PortfolioJournal clean ``` ## Architecture The app uses Clean Architecture with MVVM pattern: ``` PortfolioJournal/ ├── App/ # Entry point: PortfolioJournalApp.swift, AppDelegate, ContentView ├── Models/CoreData/ # Core Data entities and CoreDataStack singleton ├── Repositories/ # Data access layer with @MainActor CRUD operations ├── Services/ # Business logic (CalculationService, PredictionEngine, IAPService, etc.) ├── ViewModels/ # MVVM view models for each feature ├── Views/ # SwiftUI views organized by feature │ ├── Dashboard/ # Main dashboard with evolution charts │ ├── Charts/ # Financial visualizations (allocation, performance, drawdown) │ ├── Sources/ # Investment source management │ ├── Goals/ # Goal tracking and progress │ ├── Journal/ # Journal entries │ ├── Settings/ # App settings and import/export │ ├── Security/ # Face ID/PIN lock (AppLockView) │ └── Components/ # Shared UI components ├── Utilities/ # Helpers: KeychainService, FreemiumValidator, formatters, extensions └── Resources/ # Info.plist, PrivacyInfo.xcprivacy, assets PortfolioJournalWidget/ # iOS Home Screen Widget (WidgetKit) PortfolioJournalWatch/ # watchOS app (read-only portfolio view) PortfolioJournalWatchWidget/# watchOS complications (WidgetKit) Shared/ # Types shared between iOS app and watch targets ``` ### Apple Watch The watch app and its complications are read-only; every edit still happens on the iPhone. App Groups are not shared between iOS and watchOS, so the watch cannot read the Core Data store the iOS widget reads. Instead: - `WatchSyncService` (iOS) builds a `WatchPortfolioSnapshot` and pushes it as the WatchConnectivity application context. It is triggered from `CoreDataStack.refreshWidgetData()`, the same hook that reloads the iOS widget. - `WatchDataStore` (watchOS) receives it, caches it in the watch App Group via `WatchSnapshotCache`, and reloads the complication timelines. - The complication extension only reads that cache — it never talks to WatchConnectivity itself. Watch targets keep their own `*.lproj/Localizable.strings` with just their keys, like the other extensions. ### Core Data Model Key entities: `Account`, `InvestmentSource`, `Snapshot`, `Category`, `Goal`, `Asset`, `Transaction`, `AppSettings`, `PremiumStatus` Data flows through `CoreDataStack` singleton which manages CloudKit sync and AppGroup shared container for widget access. ### Key Services - **CalculationService**: Portfolio metrics, returns calculation, allocation analysis - **PredictionEngine**: Investment forecasting algorithms with caching - **IAPService**: StoreKit 2 in-app purchases - **DiagnosticsCollector**: on-device MetricKit crash/hang reports (nothing is uploaded) - **ImportService/ExportService**: CSV data import/export - **AppLockService**: Biometric/PIN security via Keychain ## Dependencies **No third-party packages.** The app deliberately links nothing outside Apple's SDKs: AdMob, Firebase Analytics and Crashlytics were removed in 1.7.0 so that the "no tracking, no analytics" claim on the App Store listing is literally true. Do not reintroduce an advertising, analytics or crash-reporting SDK. Native frameworks: SwiftUI, Combine, CoreData, CloudKit, WidgetKit, StoreKit 2, LocalAuthentication, MetricKit ## App Initialization Flow ``` PortfolioJournalApp (@main) └── AppDelegate (MetricKit diagnostics, Notifications init) └── ContentView ├── OnboardingView (first launch) ├── AppLockView (if security enabled) └── TabBar: Dashboard | Sources | Goals | Journal | Settings ``` ## Localization Supported languages: English (`en.lproj`), Spanish (`es-ES.lproj`) ## Development Notes - Use `SampleDataService` to generate demo data for testing - Premium features are gated via `FreemiumValidator` - Widget shares data through AppGroup container - Sensitive data stored in Keychain via `KeychainService`