# Platform Notes
- We're building an iOS app with modern Swift. We're targeting iOS 18. We expect to use the latest (as of Spring 2025) iOS SDK API updates and Swift language updates. One exception: we prefer to use CoreData over SwiftData for now.
- We're striving for an Apple Design Award, and expect our app to be solely focused on Apple's ecosystem. 
## SwiftUI and Apple Design Language
Given our Platform Notes above, here's a few SwiftUI specific guidelines to keep in mind:
1. Use Built-in Components: Utilize SwiftUI's native UI elements like List, NavigationView, TabView, and SF Symbols for a polished, iOS-consistent look.
2. Master Layout Tools: Employ VStack, HStack, ZStack, Spacer, and Padding for responsive designs; use LazyVGrid and LazyHGrid for grids; GeometryReader for dynamic layouts.
3. Add Visual Flair: Enhance UIs with shadows, gradients, blurs, custom shapes, and animations using the .animation() modifier for smooth transitions.
4. Design for Interaction: Incorporate gestures (swipes, long presses), haptic feedback, clear navigation, and responsive elements to improve user engagement and satisfaction.
## Swift Architecture Pattern Preferences
- Let's generally stick to MVVM, but it's ok to be flexible.
- When possible, we want to mimic a Redux pattern for state management. State should flow from a higher view, eg. an EnvironmentObject. Singletons may useful as a first step, but should be refactored for easier testing.
- We care deeply about data privacy, so we should keep as much data and processing on-device as possible. For Hematica, the only external API call we should make is to our LLM provider. If absolutely necesary, we can consider using CloudKit for server/syncing capabilities. 
- Use modern Swift 6+ and SwiftUI APIs and best practices. For example:  use environment objects (@Observable) or inject dependencies through initializers, Swift concurrency natives (eg. async/await)
- For navigation, use the newer `NavigationStack` instead of the older `NavigationView`
## Protocol Usage Guidelines
Protocols are a powerful tool for abstraction and testing, but should be used thoughtfully to avoid over-engineering. Here's when to use them:
### Use Protocols For:
1. **External Services**: Any service that interacts with external systems (eg. OCR, API calls, file system)
2. **Core Functionality**: Components that might need different implementations (eg. different OCR engines)
3. **Testable Components**: Any type that needs to be mocked for testing
4. **State Management**: Objects that manage state and might need different implementations
### Skip Protocols For:
1. **Simple Data Models**: Basic data structures and models
2. **View Logic**: SwiftUI view-specific code and logic
3. **Internal Utilities**: Helper functions and internal tools
4. **Single-Implementation Types**: Types that are unlikely to have multiple implementations
### Protocol Best Practices:
1. Keep protocols focused and small (Single Responsibility Principle)
2. Name protocols with clear, descriptive names (e.g., `DocumentTextExtractionServiceProtocol`)
3. Document the protocol's purpose and requirements
4. Consider using protocol extensions for default implementations
5. Use protocols to define clear contracts between components
## Linter errors
We're using Cursor for the AI-assistance, but still working in Xcode — but Cursor isn't properly configured with the build tools, so we end up running into environmental linter errors (eg. missing explicit imports, even though all files are in the same Xcode target.) 
Please acknowledge and ignore these linter errors instead of trying to resolve them.
# Code Style
- We should follow SRP (the Single Responsibility Principle) as often as possible. 
- We should limit lines of code (LoC) per file to ~200-300 lines. If a file is over, we should strongly consider extracting and refactoring. See our guidelines on SRP.
- Given SRP and LoC, it's ok to overload a View with extra logic if it's relatively simple. If the logic gets too complex, it should be refactored into it's own function.
- We should build features in small, incremental updates. Start with the simplest thing that works. Then, we'll iterate on it layering in more cases and complexity as-needed. 
- **Always** think critically about new code to understand if we should be re-using an existing function, or if we can modify an existing function to better handle a new case we're working on. Please avoid having multiple functions that do similar work with minor changes (eg. same function but different parameters for convenince; eg. a parsePDF function and a parseDoc function when a parseFile function will suffice.) Follow SRP.
- Do not hallucinate. For every line of code generated, you must double-check that you are using real variables, functions, and legitimate API calls.
## SwiftUI File and View Naming Conventions
- All structs conforming to the `View` protocol should be suffixed with `View` (e.g., `ProfileView`, `SparklineView`, `RainbowBarView`).
- File names should exactly match the primary `View` struct they contain. For example, a file containing `struct SparklineView: View` should be named `SparklineView.swift`.
- Follow the "one view struct per file" rule. Each SwiftUI view should reside in its own dedicated file.
- Even if a subview is small and only used within a single parent view, consider extracting it into its own file for clarity, improved discoverability, and better compatibility with tools that have context limitations.
- For related views that form a feature, organize them in a feature-specific directory (e.g., `Features/Journal/` for all journal-related views).
Today I'd like to update how we <feature_description> in our <@mention_feature_folder> feature. 
I've noticed that when ...
I think there's an issue with ...
Please share your findings, and put together a detailed implementation plan to help fix it, but don't make any changes to the code yet.
Let's work through a build-time error:
`<insert xcode error>`
Please review the source file where the error is, then adjacent files to see if you can determine the root cause. If you can determine, please share what it is, why it happened, and 2 approaches to fix it (high-level), and which approach you recommend with a detailed implementation plan. Once we agree on the plan, we'll edit code, but for now let's just review + plan.
Please keep in mind: we want to use modern Swift (6+), SwiftUI, and iOS 18+ APIs, design patterns, and best practices... while keeping in mind we're balancing for a solo dev (me), who prefers simpler code with fewer abstractions (even if trade-off is a few more lines packed into a file.)