# Implementation Guide

> Generates detailed implementation guide with pseudo-code and step-by-step development instructions. Creates IMPLEMENTATION_GUIDE.md from PRD, Architecture, and UX specs. Use when creating development roadmap.

- Skill: `rshankras/implementation-guide` (Agent Skill)
- Install (CLI): `npx skillmds add rshankras/implementation-guide`
- Raw SKILL.md: https://api.skillmd.com/api/skills/rshankras/implementation-guide/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Product & Planning
- Author: rshankras (https://skillmd.com/u/rshankras)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/rshankras/implementation-guide

---


# Implementation Guide Skill

Generate detailed implementation guide with pseudo-code and step-by-step instructions for iOS/macOS app development.

## Metadata
- **Name**: implementation-guide
- **Version**: 1.0.0
- **Role**: Senior iOS/macOS Developer
- **Author**: ProductAgent Team

## When This Skill Activates

This skill activates when the user says:
- "generate implementation guide"
- "create development guide"
- "write implementation steps"
- "generate code guide"
- "create developer guide from specs"

## Description

You are a Senior iOS/macOS Developer AI agent with expertise in Swift, SwiftUI, SwiftData, and modern iOS development patterns. Your job is to transform product requirements, architecture, and UX specifications into a comprehensive, step-by-step implementation guide that enables any competent iOS developer to build the app confidently.

## Prerequisites

Before activating this skill, ensure:
1. PRD exists (from prd-generator skill) with all features defined
2. ARCHITECTURE.md exists (from architecture-spec skill) with tech stack and structure
3. UX_SPEC.md exists (from ux-spec skill) with wireframes and interactions
4. DESIGN_SYSTEM.md exists with colors, typography, components

## Input Sources

Read and extract information from:

1. **docs/PRD.md**
   - All features and user stories
   - Acceptance criteria
   - Success metrics
   - Timeline estimates

2. **docs/ARCHITECTURE.md**
   - Architecture pattern (MVVM, Clean, TCA)
   - Technology stack decisions
   - Data models and relationships
   - Module structure
   - Networking layer design

3. **docs/UX_SPEC.md**
   - All screens and wireframes
   - User flows
   - Interactions and gestures
   - States (empty, loading, error)

4. **docs/DESIGN_SYSTEM.md**
   - Colors, typography, spacing
   - Component styles
   - Animation timings
   - Design tokens

5. **User clarifications** (ask if needed):
   - Xcode version / minimum iOS version preferences
   - Any existing codebase to integrate with
   - CI/CD preferences (Xcode Cloud, GitHub Actions, Fastlane)

## Output

Generate: **docs/IMPLEMENTATION_GUIDE.md**

Structure (comprehensive, ~3000-5000 lines):

```markdown
# Implementation Guide: [App Name]

**Version**: 1.0.0
**Last Updated**: [Date]
**Platform**: iOS [Version]+
**Language**: Swift 5.9+
**Framework**: SwiftUI
**Xcode**: 15.0+

---

## 0. Quick Start

For the impatient developer:

```bash
# 1. Clone or create new Xcode project
# Template: iOS App (SwiftUI)
# Name: [AppName]
# Organization ID: com.yourcompany.appname
# Language: Swift
# Storage: SwiftData
# Include Tests: Yes

# 2. Set minimum deployment target
# Project Settings → General → Minimum Deployments: iOS 26.0 (or iOS 17+ for broader reach)

# 3. Add dependencies via SPM (if any)
# File → Add Package Dependencies → [URLs from ARCHITECTURE.md]

# 4. Create folder structure (see Section 2)

# 5. Follow implementation phases (Section 3)

# 6. Run tests frequently
xcodebuild test -scheme [AppName]

# 7. Launch and iterate
```

**Estimated Timeline**: [X] weeks for MVP (from PRD)
**Estimated LOC**: ~[Y] lines of Swift code
**Files to Create**: ~[Z] .swift files

---

## 1. Project Setup

### 1.1 Create Xcode Project

1. Open Xcode 15+
2. File → New → Project
3. Choose template: **iOS → App**
4. Configuration:
   - **Product Name**: [AppName]
   - **Team**: [Your team or Personal Team]
   - **Organization Identifier**: com.yourcompany.appname
   - **Bundle Identifier**: [Auto-generated]
   - **Interface**: SwiftUI
   - **Language**: Swift
   - **Storage**: SwiftData [or Core Data based on ARCHITECTURE]
   - **Include Tests**: ✅ Yes
   - **Create Git repository**: ✅ Optional but recommended

5. Click Create

### 1.2 Project Configuration

**File**: Select project in Navigator → General tab

**Deployment Info**:
- **Minimum Deployments**: iOS 26.0 [adjust based on ARCHITECTURE — iOS 17+ still supported for broader reach]
- **Supported Destinations**: iPhone (✅), iPad (based on requirements)
- **Device Orientation**:
  - Portrait (✅ Required)
  - Landscape Left (based on requirements)
  - Landscape Right (based on requirements)

**App Icons & Launch Screen**:
- **App Icon**: Add 1024x1024 icon to Assets.xcassets/AppIcon
- **Launch Screen**: Use default or customize LaunchScreen.storyboard

**Signing & Capabilities**:
- **Team**: Select your development team
- **Signing Certificate**: Automatically manage signing (recommended)
- **Capabilities**: Add as needed:
  - Push Notifications (if required)
  - iCloud (if using CloudKit sync)
  - Background Modes (if needed)

### 1.3 Add Dependencies (if any)

**From ARCHITECTURE.md**, add these packages:

**Example** (adjust based on actual ARCHITECTURE):
```
File → Add Package Dependencies

[If networking library needed]
1. Alamofire: https://github.com/Alamofire/Alamofire
   Version: 5.9.0+

[If image loading needed]
2. Kingfisher: https://github.com/onevcat/Kingfisher
   Version: 7.10.0+

[Add only packages specified in ARCHITECTURE.md]
```

**Important**: Minimize third-party dependencies. Use native frameworks when possible.

### 1.4 Configure SwiftData

**File**: [AppName]App.swift

```swift
import SwiftUI
import SwiftData

@main
struct AppNameApp: App {
    // Define the data model container
    var sharedModelContainer: ModelContainer = {
        let schema = Schema([
            // List all @Model classes here
            User.self,
            Item.self,
            // Add all data models from ARCHITECTURE.md
        ])

        let modelConfiguration = ModelConfiguration(
            schema: schema,
            isStoredInMemoryOnly: false  // Persist to disk
        )

        do {
            return try ModelContainer(
                for: schema,
                configurations: [modelConfiguration]
            )
        } catch {
            fatalError("Could not create ModelContainer: \\(error)")
        }
    }()

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(sharedModelContainer)
    }
}
```

---

## 2. File Structure

Create this folder hierarchy in your project:

```
[AppName]/
├── App/
│   ├── [AppName]App.swift           # Entry point
│   └── ContentView.swift            # Root view (delete if not using)
│
├── Features/                        # Feature modules
│   ├── Onboarding/
│   │   ├── Views/
│   │   │   ├── OnboardingView.swift
│   │   │   ├── OnboardingStep1View.swift
│   │   │   └── OnboardingStep2View.swift
│   │   └── ViewModels/
│   │       └── OnboardingViewModel.swift
│   │
│   ├── Home/
│   │   ├── Views/
│   │   │   ├── HomeView.swift
│   │   │   ├── HomeCardView.swift
│   │   │   └── HomeEmptyStateView.swift
│   │   ├── ViewModels/
│   │   │   └── HomeViewModel.swift
│   │   └── Models/
│   │       └── HomeFilter.swift         # View-specific models
│   │
│   ├── ItemDetail/
│   │   ├── Views/
│   │   │   ├── ItemDetailView.swift
│   │   │   └── ItemDetailHeaderView.swift
│   │   └── ViewModels/
│   │       └── ItemDetailViewModel.swift
│   │
│   ├── AddEditItem/
│   │   ├── Views/
│   │   │   └── AddEditItemView.swift
│   │   └── ViewModels/
│   │       └── AddEditItemViewModel.swift
│   │
│   └── Settings/
│       ├── Views/
│       │   ├── SettingsView.swift
│       │   └── AccountView.swift
│       └── ViewModels/
│           └── SettingsViewModel.swift
│
├── Core/                            # Shared infrastructure
│   ├── Networking/
│   │   ├── APIClient.swift          # Base HTTP client
│   │   ├── Endpoint.swift           # API endpoint definitions
│   │   ├── NetworkError.swift       # Error types
│   │   └── APIService.swift         # High-level API service
│   │
│   ├── Storage/
│   │   ├── DataManager.swift        # SwiftData operations wrapper
│   │   └── CacheManager.swift       # Optional: in-memory cache
│   │
│   ├── Extensions/
│   │   ├── View+Extensions.swift    # SwiftUI view modifiers
│   │   ├── Color+Extensions.swift   # Design system colors
│   │   ├── Font+Extensions.swift    # Custom font extensions
│   │   └── Date+Extensions.swift    # Date formatting
│   │
│   ├── Utilities/
│   │   ├── Logger.swift             # Logging utility
│   │   ├── Validator.swift          # Input validation
│   │   └── Constants.swift          # App constants
│   │
│   └── DesignSystem/
│       └── DesignTokens.swift       # Centralized design tokens
│
├── Models/                          # Data models (SwiftData)
│   ├── User.swift
│   ├── Item.swift
│   ├── Category.swift
│   └── [Other models from ARCHITECTURE.md]
│
├── Services/                        # Business logic services
│   ├── AuthenticationService.swift  # If auth required
│   ├── SyncService.swift            # If sync required
│   └── NotificationService.swift    # If notifications required
│
├── Resources/                       # Assets and resources
│   ├── Assets.xcassets/
│   │   ├── AppIcon.appiconset/
│   │   ├── Colors/                  # Define colors here
│   │   │   ├── BrandPrimary.colorset
│   │   │   ├── BrandSecondary.colorset
│   │   │   └── [All colors from DESIGN_SYSTEM.md]
│   │   └── Images/
│   └── PrivacyInfo.xcprivacy        # Privacy manifest
│
└── Supporting Files/
    ├── Info.plist
    └── [AppName].entitlements       # If capabilities needed

[AppName]Tests/                      # Unit tests
├── ViewModelTests/
│   ├── HomeViewModelTests.swift
│   └── [Other ViewModel tests]
├── ModelTests/
│   ├── UserTests.swift
│   └── [Other Model tests]
└── ServiceTests/
    └── APIClientTests.swift

[AppName]UITests/                    # UI tests
└── [AppName]UITests.swift
```

**To Create Folders**:
1. Right-click project in Navigator
2. New Group (⌘⌥N)
3. Name it exactly as above
4. Create subgroups as needed
5. Add files to appropriate groups

---

## 3. Implementation Phases

Follow these phases sequentially. Each phase builds on the previous.

### **Phase 1: Core Infrastructure** (Week 1)

Goal: Set up foundational code that all features depend on.

---

#### Step 1.1: Create Data Models

For each entity in ARCHITECTURE.md Section 3.2, create a SwiftData model.

**File**: `Models/User.swift`

**Pseudo-code with inline documentation**:

```swift
import Foundation
import SwiftData

/// Represents a user of the application
/// SwiftData model - automatically persisted to local database
@Model
final class User {
    // MARK: - Properties

    /// Unique identifier for the user
    /// @Attribute(.unique) ensures no duplicate UUIDs in database
    @Attribute(.unique) var id: UUID

    /// User's full name
    var name: String

    /// User's email address (used for login and notifications)
    var email: String

    /// URL to user's profile image (optional)
    var profileImageURL: String?

    /// Timestamp when user account was created
    var createdAt: Date

    /// Timestamp of last profile update
    var updatedAt: Date

    // MARK: - Relationships

    /// All items created by this user
    /// @Relationship with deleteRule .cascade means: when User is deleted, all their Items are also deleted
    @Relationship(deleteRule: .cascade, inverse: \\Item.owner)
    var items: [Item]

    // MARK: - Initializer

    /// Creates a new User instance
    /// - Parameters:
    ///   - name: User's full name
    ///   - email: User's email address
    init(name: String, email: String) {
        self.id = UUID()
        self.name = name
        self.email = email
        self.profileImageURL = nil
        self.createdAt = Date()
        self.updatedAt = Date()
        self.items = []
    }

    // MARK: - Computed Properties

    /// Returns formatted display name (first name only if space exists)
    var displayName: String {
        let components = name.components(separatedBy: " ")
        return components.first ?? name
    }

    /// Returns user's initials for avatar fallback (e.g., "John Doe" → "JD")
    var initials: String {
        let components = name.components(separatedBy: " ")
        let initials = components.compactMap { $0.first }.prefix(2)
        return String(initials).uppercased()
    }

    // MARK: - Validation

    /// Validates if user data is complete and valid
    /// - Returns: true if valid, false otherwise
    var isValid: Bool {
        return !name.isEmpty && isValidEmail(email)
    }

    /// Validates email format using regex
    private func isValidEmail(_ email: String) -> Bool {
        let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\\\.[A-Za-z]{2,64}"
        let emailPredicate = NSPredicate(format: "SELF MATCHES %@", emailRegex)
        return emailPredicate.evaluate(with: email)
    }

    // MARK: - Methods

    /// Updates the user's profile information
    /// - Parameters:
    ///   - name: New name (optional)
    ///   - email: New email (optional)
    ///   - profileImageURL: New profile image URL (optional)
    func updateProfile(name: String? = nil, email: String? = nil, profileImageURL: String? = nil) {
        if let name = name {
            self.name = name
        }
        if let email = email {
            self.email = email
        }
        if let profileImageURL = profileImageURL {
            self.profileImageURL = profileImageURL
        }
        self.updatedAt = Date()
    }
}

// MARK: - Codable Conformance (for API sync)

extension User: Codable {
    enum CodingKeys: String, CodingKey {
        case id
        case name
        case email
        case profileImageURL = "profile_image_url"  // Match API naming
        case createdAt = "created_at"
        case updatedAt = "updated_at"
    }
}
```

**Implementation Notes**:
- Use `@Model` macro for SwiftData (automatic persistence)
- Mark unique fields with `@Attribute(.unique)`
- Define relationships with `@Relationship(deleteRule:inverse:)`
- Add validation methods for data integrity
- Use `final` for classes that don't need subclassing (performance)
- Add `Codable` conformance if syncing with backend API

**Repeat for all models** listed in ARCHITECTURE.md:
- `Models/Item.swift`
- `Models/Category.swift`
- [Any other models]

---

**File**: `Models/Item.swift`

**Pseudo-code**:

```swift
import Foundation
import SwiftData

/// Represents an item in the application
@Model
final class Item {
    @Attribute(.unique) var id: UUID
    var title: String
    var subtitle: String?
    var itemDescription: String
    var thumbnailURL: String?
    var status: ItemStatus
    var metadata: String?  // JSON string for flexible data
    var createdAt: Date
    var updatedAt: Date

    // Relationships
    @Relationship(inverse: \\User.items)
    var owner: User?

    @Relationship(inverse: \\Category.items)
    var category: Category?

    init(title: String, description: String, owner: User, category: Category? = nil) {
        self.id = UUID()
        self.title = title
        self.subtitle = nil
        self.itemDescription = description
        self.thumbnailURL = nil
        self.status = .active
        self.metadata = nil
        self.createdAt = Date()
        self.updatedAt = Date()
        self.owner = owner
        self.category = category
    }

    var isValid: Bool {
        return !title.isEmpty && !itemDescription.isEmpty
    }

    func updateStatus(_ newStatus: ItemStatus) {
        self.status = newStatus
        self.updatedAt = Date()
    }
}

/// Item status enum
enum ItemStatus: String, Codable {
    case active = "active"
    case pending = "pending"
    case completed = "completed"
    case archived = "archived"
}

// Make ItemStatus compatible with SwiftData
extension ItemStatus: RawRepresentable {}
```

---

#### Step 1.2: Setup Data Manager

**Purpose**: Centralized service for all SwiftData operations (CRUD + queries)

**File**: `Core/Storage/DataManager.swift`

**Pseudo-code**:

```swift
import Foundation
import SwiftData
import Observation

/// Centralized manager for all SwiftData operations
/// Use this instead of direct ModelContext access for consistency
@Observable
final class DataManager {
    // MARK: - Properties

    /// Shared singleton instance (use dependency injection in production)
    static let shared = DataManager()

    /// SwiftData container holding the schema and configurations
    let container: ModelContainer

    /// Main context for UI-related operations (runs on main thread)
    var mainContext: ModelContext

    // MARK: - Initialization

    /// Private init for singleton
    private init() {
        // Define schema with all model types
        let schema = Schema([
            User.self,
            Item.self,
            Category.self,
            // Add all @Model classes here
        ])

        // Configure persistence
        let modelConfiguration = ModelConfiguration(
            schema: schema,
            isStoredInMemoryOnly: false,  // false = persist to disk
            allowsSave: true
        )

        do {
            // Create container
            self.container = try ModelContainer(
                for: schema,
                configurations: [modelConfiguration]
            )

            // Get main context
            self.mainContext = container.mainContext

            // Configure context
            mainContext.autosaveEnabled = true  // Auto-save on changes

            print("✅ DataManager initialized successfully")
        } catch {
            fatalError("Failed to create ModelContainer: \\(error)")
        }
    }

    // MARK: - Generic CRUD Operations

    /// Creates and inserts a new model instance
    /// - Parameter model: The model instance to insert
    /// - Throws: Error if save fails
    func create<T: PersistentModel>(_ model: T) throws {
        mainContext.insert(model)
        try save()
    }

    /// Fetches all instances of a model type
    /// - Parameters:
    ///   - type: The model type to fetch
    ///   - predicate: Optional filter (nil = fetch all)
    ///   - sortBy: Optional sort descriptors
    /// - Returns: Array of model instances
    /// - Throws: Error if fetch fails
    func fetch<T: PersistentModel>(
        _ type: T.Type,
        predicate: Predicate<T>? = nil,
        sortBy: [SortDescriptor<T>] = []
    ) throws -> [T] {
        var fetchDescriptor = FetchDescriptor<T>(predicate: predicate, sortBy: sortBy)
        return try mainContext.fetch(fetchDescriptor)
    }

    /// Fetches a single instance by ID
    /// - Parameters:
    ///   - type: The model type
    ///   - id: The persistent model ID
    /// - Returns: Model instance or nil if not found
    func fetchByID<T: PersistentModel>(_ type: T.Type, id: PersistentIdentifier) -> T? {
        return mainContext.model(for: id) as? T
    }

    /// Updates a model (no-op, changes are tracked automatically)
    /// Just call save() after modifying properties
    func update() throws {
        try save()
    }

    /// Deletes a model instance
    /// - Parameter model: The model instance to delete
    /// - Throws: Error if delete/save fails
    func delete<T: PersistentModel>(_ model: T) throws {
        mainContext.delete(model)
        try save()
    }

    /// Deletes all instances of a model type
    /// - Parameter type: The model type to delete all of
    /// - Throws: Error if delete fails
    func deleteAll<T: PersistentModel>(_ type: T.Type) throws {
        let all = try fetch(type)
        for item in all {
            mainContext.delete(item)
        }
        try save()
    }

    /// Saves pending changes to persistent store
    /// - Throws: Error if save fails
    private func save() throws {
        if mainContext.hasChanges {
            try mainContext.save()
        }
    }

    // MARK: - Background Context

    /// Creates a background context for heavy operations (imports, sync)
    /// - Returns: A new ModelContext for background thread
    func backgroundContext() -> ModelContext {
        return ModelContext(container)
    }

    // MARK: - Specialized Queries (Domain-Specific)

    /// Fetches items filtered by status
    /// - Parameter status: The item status to filter by
    /// - Returns: Array of items with matching status
    /// - Throws: Error if fetch fails
    func fetchItems(byStatus status: ItemStatus) throws -> [Item] {
        let predicate = #Predicate<Item> { item in
            item.status == status
        }
        let sortBy = [SortDescriptor(\\Item.createdAt, order: .reverse)]
        return try fetch(Item.self, predicate: predicate, sortBy: sortBy)
    }

    /// Fetches recent items (last N days)
    /// - Parameter days: Number of days to look back
    /// - Returns: Array of recent items
    /// - Throws: Error if fetch fails
    func fetchRecentItems(days: Int = 7) throws -> [Item] {
        let startDate = Calendar.current.date(byAdding: .day, value: -days, to: Date())!
        let predicate = #Predicate<Item> { item in
            item.createdAt >= startDate
        }
        let sortBy = [SortDescriptor(\\Item.createdAt, order: .reverse)]
        return try fetch(Item.self, predicate: predicate, sortBy: sortBy)
    }

    /// Searches items by title or description
    /// - Parameter query: Search query string
    /// - Returns: Array of matching items
    /// - Throws: Error if fetch fails
    func searchItems(query: String) throws -> [Item] {
        let lowercaseQuery = query.lowercased()
        let predicate = #Predicate<Item> { item in
            item.title.lowercased().contains(lowercaseQuery) ||
            item.itemDescription.lowercased().contains(lowercaseQuery)
        }
        return try fetch(Item.self, predicate: predicate)
    }

    // Add more domain-specific queries as needed from PRD features
}

// MARK: - Error Handling

enum DataManagerError: LocalizedError {
    case fetchFailed(Error)
    case saveFailed(Error)
    case deleteFailed(Error)
    case notFound

    var errorDescription: String? {
        switch self {
        case .fetchFailed(let error):
            return "Failed to fetch data: \\(error.localizedDescription)"
        case .saveFailed(let error):
            return "Failed to save data: \\(error.localizedDescription)"
        case .deleteFailed(let error):
            return "Failed to delete data: \\(error.localizedDescription)"
        case .notFound:
            return "Item not found"
        }
    }
}
```

**Testing DataManager**:

Create `Tests/ServiceTests/DataManagerTests.swift`:

```swift
import XCTest
@testable import [AppName]

final class DataManagerTests: XCTestCase {
    var dataManager: DataManager!

    override func setUp() {
        super.setUp()
        // Use in-memory store for tests
        dataManager = DataManager.shared
    }

    override func tearDown() {
        // Clean up test data
        try? dataManager.deleteAll(Item.self)
        try? dataManager.deleteAll(User.self)
        dataManager = nil
        super.tearDown()
    }

    func testCreateUser() throws {
        // Given
        let user = User(name: "Test User", email: "test@example.com")

        // When
        try dataManager.create(user)

        // Then
        let fetched = try dataManager.fetch(User.self)
        XCTAssertEqual(fetched.count, 1)
        XCTAssertEqual(fetched.first?.name, "Test User")
    }

    func testFetchItemsByStatus() throws {
        // Given
        let user = User(name: "Test", email: "test@test.com")
        try dataManager.create(user)

        let item1 = Item(title: "Active", description: "Test", owner: user)
        item1.status = .active
        try dataManager.create(item1)

        let item2 = Item(title: "Complete", description: "Test", owner: user)
        item2.status = .completed
        try dataManager.create(item2)

        // When
        let activeItems = try dataManager.fetchItems(byStatus: .active)

        // Then
        XCTAssertEqual(activeItems.count, 1)
        XCTAssertEqual(activeItems.first?.title, "Active")
    }

    // Add more tests for each DataManager method
}
```

---

#### Step 1.3: Implement Design System

**Purpose**: Centralize all design tokens (colors, typography, spacing) in one file

**File**: `Core/DesignSystem/DesignTokens.swift`

**Complete implementation** (copy from DESIGN_SYSTEM.md Section 12):

```swift
import SwiftUI

/// Centralized design system tokens
/// All design decisions are defined here - reference throughout the app
enum DesignSystem {

    // MARK: - Colors

    enum Colors {
        // Brand colors (defined in Assets.xcassets/Colors/)
        static let brandPrimary = Color("BrandPrimary")
        static let brandSecondary = Color("BrandSecondary")
        static let brandAccent = Color("BrandAccent")

        // Semantic colors
        static let success = Color.green
        static let warning = Color.orange
        static let error = Color.red
        static let info = Color.blue

        // Text colors (use system colors for automatic dark mode)
        static let textPrimary = Color.primary
        static let textSecondary = Color.secondary

        // Background colors
        static let background = Color(.systemBackground)
        static let secondaryBackground = Color(.secondarySystemBackground)
        static let tertiaryBackground = Color(.tertiarySystemBackground)

        // UI element colors
        static let separator = Color(.separator)
        static let border = Color(.separator)
    }

    // MARK: - Typography

    enum Typography {
        static let largeTitle = Font.largeTitle
        static let title = Font.title
        static let title2 = Font.title2
        static let title3 = Font.title3
        static let headline = Font.headline
        static let body = Font.body
        static let callout = Font.callout
        static let subheadline = Font.subheadline
        static let footnote = Font.footnote
        static let caption = Font.caption
        static let caption2 = Font.caption2
    }

    // MARK: - Spacing

    enum Spacing {
        static let xxs: CGFloat = 2
        static let xs: CGFloat = 4
        static let s: CGFloat = 8
        static let m: CGFloat = 12
        static let l: CGFloat = 16     // Default
        static let xl: CGFloat = 24
        static let xxl: CGFloat = 32
        static let xxxl: CGFloat = 48
    }

    // MARK: - Corner Radius

    enum Radius {
        static let xs: CGFloat = 4
        static let small: CGFloat = 8
        static let medium: CGFloat = 12   // Default
        static let large: CGFloat = 16
        static let xl: CGFloat = 24
        static let full: CGFloat = 9999   // Fully rounded
    }

    // MARK: - Shadows

    enum Shadow {
        static let card = (color: Color.black.opacity(0.1), radius: CGFloat(8), x: CGFloat(0), y: CGFloat(2))
        static let modal = (color: Color.black.opacity(0.15), radius: CGFloat(16), x: CGFloat(0), y: CGFloat(4))
        static let elevated = (color: Color.black.opacity(0.2), radius: CGFloat(24), x: CGFloat(0), y: CGFloat(8))
    }

    // MARK: - Animation

    enum Animation {
        static let fast: Double = 0.2
        static let standard: Double = 0.3
        static let slow: Double = 0.5
        static let verySlow: Double = 1.0
    }

    // MARK: - Layout

    enum Layout {
        static let cardHeight: CGFloat = 80
        static let buttonHeight: CGFloat = 50
        static let textFieldHeight: CGFloat = 50
        static let minTapTarget: CGFloat = 44
        static let maxContentWidth: CGFloat = 600  // For iPad
    }
}

// MARK: - Convenience Extensions

extension Color {
    /// Initialize from hex string
    init(hex: String) {
        let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
        var int: UInt64 = 0
        Scanner(string: hex).scanHexInt64(&int)
        let a, r, g, b: UInt64
        switch hex.count {
        case 3: // RGB (12-bit)
            (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
        case 6: // RGB (24-bit)
            (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
        case 8: // ARGB (32-bit)
            (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
        default:
            (a, r, g, b) = (1, 1, 1, 0)
        }

        self.init(
            .sRGB,
            red: Double(r) / 255,
            green: Double(g) / 255,
            blue:  Double(b) / 255,
            opacity: Double(a) / 255
        )
    }
}
```

**Add Color Assets**:

1. Open `Assets.xcassets`
2. Right-click → New Color Set
3. Name: "BrandPrimary"
4. In Attributes Inspector: Appearances → Any, Dark
5. Set Light Mode color: #007AFF (or from DESIGN_SYSTEM.md)
6. Set Dark Mode color: #0A84FF
7. Repeat for "BrandSecondary", "BrandAccent", etc.

---

#### Step 1.4: Create View Extensions

**Purpose**: Reusable SwiftUI modifiers for consistent styling

**File**: `Core/Extensions/View+Extensions.swift`

**Implementation**:

```swift
import SwiftUI

extension View {
    // MARK: - Card Style

    /// Applies standard card styling
    /// - Returns: View with card background, padding, corner radius, and shadow
    func cardStyle() -> some View {
        self
            .padding(DesignSystem.Spacing.l)
            .background(DesignSystem.Colors.secondaryBackground)
            .cornerRadius(DesignSystem.Radius.medium)
            .shadow(
                color: DesignSystem.Shadow.card.color,
                radius: DesignSystem.Shadow.card.radius,
                x: DesignSystem.Shadow.card.x,
                y: DesignSystem.Shadow.card.y
            )
    }

    // MARK: - Button Styles

    /// Applies primary button styling
    func primaryButtonStyle() -> some View {
        self
            .font(DesignSystem.Typography.headline)
            .foregroundColor(.white)
            .frame(maxWidth: .infinity)
            .frame(height: DesignSystem.Layout.buttonHeight)
            .background(DesignSystem.Colors.brandPrimary)
            .cornerRadius(DesignSystem.Radius.medium)
    }

    /// Applies secondary button styling (outlined)
    func secondaryButtonStyle() -> some View {
        self
            .font(DesignSystem.Typography.headline)
            .foregroundColor(DesignSystem.Colors.brandPrimary)
            .frame(maxWidth: .infinity)
            .frame(height: DesignSystem.Layout.buttonHeight)
            .background(Color.clear)
            .cornerRadius(DesignSystem.Radius.medium)
            .overlay(
                RoundedRectangle(cornerRadius: DesignSystem.Radius.medium)
                    .stroke(DesignSystem.Colors.brandPrimary, lineWidth: 2)
            )
    }

    /// Applies text button styling (no background)
    func textButtonStyle() -> some View {
        self
            .font(DesignSystem.Typography.body)
            .foregroundColor(DesignSystem.Colors.brandPrimary)
    }

    // MARK: - Loading Overlay

    /// Shows loading overlay when condition is true
    /// - Parameter isLoading: Binding to loading state
    func loadingOverlay(isLoading: Bool) -> some View {
        self.overlay {
            if isLoading {
                ZStack {
                    Color.black.opacity(0.3)
                        .ignoresSafeArea()

                    ProgressView()
                        .controlSize(.large)
                        .padding()
                        .background(.ultraThinMaterial)
                        .cornerRadius(DesignSystem.Radius.medium)
                }
            }
        }
    }

    // MARK: - Conditional Modifiers

    /// Applies modifier only when condition is true
    @ViewBuilder
    func `if`<Transform: View>(
        _ condition: Bool,
        transform: (Self) -> Transform
    ) -> some View {
        if condition {
            transform(self)
        } else {
            self
        }
    }

    // MARK: - Keyboard Dismissal

    /// Adds tap gesture to dismiss keyboard
    func dismissKeyboardOnTap() -> some View {
        self.onTapGesture {
            UIApplication.shared.sendAction(
                #selector(UIResponder.resignFirstResponder),
                to: nil,
                from: nil,
                for: nil
            )
        }
    }
}

// MARK: - Button Style Structs

struct PrimaryButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .primaryButtonStyle()
            .scaleEffect(configuration.isPressed ? 0.98 : 1.0)
            .animation(.easeInOut(duration: DesignSystem.Animation.fast), value: configuration.isPressed)
    }
}

struct SecondaryButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .secondaryButtonStyle()
            .opacity(configuration.isPressed ? 0.7 : 1.0)
            .animation(.easeInOut(duration: DesignSystem.Animation.fast), value: configuration.isPressed)
    }
}

// Usage:
// Button("Continue") { }
//     .buttonStyle(PrimaryButtonStyle())
```

---

#### Step 1.5: Create Networking Layer

**Purpose**: Centralized HTTP client for API calls

**File**: `Core/Networking/APIClient.swift`

**Implementation**:

```swift
import Foundation

/// Actor-based API client for thread-safe network operations
actor APIClient {
    // MARK: - Properties

    /// Shared singleton instance
    static let shared = APIClient()

    /// Base URL for API
    private let baseURL: URL

    /// URLSession for network requests
    private let session: URLSession

    // MARK: - Initialization

    init(baseURL: String = "https://api.example.com") {
        self.baseURL = URL(string: baseURL)!

        let config = URLSessionConfiguration.default
        config.timeoutIntervalForRequest = 30
        config.timeoutIntervalForResource = 60
        config.waitsForConnectivity = true
        self.session = URLSession(configuration: config)
    }

    // MARK: - Generic Request Method

    /// Performs an API request and decodes the response
    /// - Parameters:
    ///   - endpoint: The API endpoint to call
    ///   - method: HTTP method (GET, POST, etc.)
    ///   - body: Optional request body (will be JSON encoded)
    ///   - headers: Additional headers
    /// - Returns: Decoded response of type T
    /// - Throws: APIError if request fails
    func request<T: Decodable>(
        _ endpoint: String,
        method: HTTPMethod = .get,
        body: Encodable? = nil,
        headers: [String: String] = [:]
    ) async throws -> T {
        // Build URL
        guard let url = URL(string: endpoint, relativeTo: baseURL) else {
            throw APIError.invalidURL
        }

        // Create request
        var request = URLRequest(url: url)
        request.httpMethod = method.rawValue

        // Add default headers
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json", forHTTPHeaderField: "Accept")

        // Add custom headers
        for (key, value) in headers {
            request.setValue(value, forHTTPHeaderField: key)
        }

        // Add authentication header (if user is logged in)
        // Uncomment if auth required:
        // if let token = try? await getAuthToken() {
        //     request.setValue("Bearer \\(token)", forHTTPHeaderField: "Authorization")
        // }

        // Encode body
        if let body = body {
            request.httpBody = try JSONEncoder().encode(body)
        }

        // Perform request
        let (data, response) = try await session.data(for: request)

        // Validate response
        guard let httpResponse = response as? HTTPURLResponse else {
            throw APIError.invalidResponse
        }

        // Handle HTTP status codes
        switch httpResponse.statusCode {
        case 200...299:
            // Success - decode response
            let decoder = JSONDecoder()
            decoder.keyDecodingStrategy = .convertFromSnakeCase
            decoder.dateDecodingStrategy = .iso8601

            do {
                return try decoder.decode(T.self, from: data)
            } catch {
                print("❌ Decoding error: \\(error)")
                print("Response data: \\(String(data: data, encoding: .utf8) ?? "")")
                throw APIError.decodingError(error)
            }

        case 401:
            throw APIError.unauthorized

        case 403:
            throw APIError.forbidden

        case 404:
            throw APIError.notFound

        case 500...599:
            throw APIError.serverError(httpResponse.statusCode)

        default:
            throw APIError.httpError(httpResponse.statusCode)
        }
    }

    // MARK: - Convenience Methods

    /// Performs a GET request
    func get<T: Decodable>(_ endpoint: String) async throws -> T {
        return try await request(endpoint, method: .get)
    }

    /// Performs a POST request
    func post<T: Decodable>(_ endpoint: String, body: Encodable) async throws -> T {
        return try await request(endpoint, method: .post, body: body)
    }

    /// Performs a PUT request
    func put<T: Decodable>(_ endpoint: String, body: Encodable) async throws -> T {
        return try await request(endpoint, method: .put, body: body)
    }

    /// Performs a DELETE request
    func delete<T: Decodable>(_ endpoint: String) async throws -> T {
        return try await request(endpoint, method: .delete)
    }
}

// MARK: - HTTP Method

enum HTTPMethod: String {
    case get = "GET"
    case post = "POST"
    case put = "PUT"
    case delete = "DELETE"
    case patch = "PATCH"
}

// MARK: - API Error

enum APIError: LocalizedError {
    case invalidURL
    case invalidResponse
    case unauthorized
    case forbidden
    case notFound
    case httpError(Int)
    case serverError(Int)
    case decodingError(Error)
    case networkError(Error)

    var errorDescription: String? {
        switch self {
        case .invalidURL:
            return "Invalid URL"
        case .invalidResponse:
            return "Invalid response from server"
        case .unauthorized:
            return "Unauthorized. Please log in again."
        case .forbidden:
            return "You don't have permission to access this resource"
        case .notFound:
            return "Resource not found"
        case .httpError(let code):
            return "HTTP error: \\(code)"
        case .serverError(let code):
            return "Server error: \\(code)"
        case .decodingError(let error):
            return "Failed to decode response: \\(error.localizedDescription)"
        case .networkError(let error):
            return "Network error: \\(error.localizedDescription)"
        }
    }
}

// MARK: - Usage Example

extension APIClient {
    // Example: Fetch items from API
    func fetchItems() async throws -> [Item] {
        return try await get("/items")
    }

    // Example: Create new item
    func createItem(_ item: Item) async throws -> Item {
        return try await post("/items", body: item)
    }

    // Add all API endpoints from ARCHITECTURE.md here
}
```

---

**Phase 1 Complete!** ✅

At this point, you have:
- ✅ All data models defined
- ✅ DataManager for CRUD operations
- ✅ Design system tokens centralized
- ✅ Reusable view modifiers
- ✅ Networking layer ready

---

### **Phase 2: Feature Implementation** (Weeks 2-4)

Now implement each screen from UX_SPEC.md, one feature at a time.

[Due to character limit, I'll provide the structure for one complete feature, which you repeat for all features]

---

#### Step 2.1: Implement Home Screen

**Goal**: Create the main content view where users see their items

**Files to create**:
- `Features/Home/Views/HomeView.swift`
- `Features/Home/Views/HomeCardView.swift`
- `Features/Home/Views/HomeEmptyStateView.swift`
- `Features/Home/ViewModels/HomeViewModel.swift`

---

**File**: `Features/Home/ViewModels/HomeViewModel.swift`

**Purpose**: Business logic and state management for Home screen

```swift
import Foundation
import SwiftUI
import SwiftData
import Observation

/// View model for Home screen
///

…(truncated)
