Implementation Guide Skill

SkillAI & models

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.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Implementation Guide Skill skill

What this skill tells your AI

The instructions your AI receives, as published by rshankras/claude-code-apple-skills in skills/product/implementation-guide/SKILL.md and read by ahel’s review.

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):

# 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

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:

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:

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:

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:

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

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
727
Forks
70
Last commit
Jul 2026
Advanced
Catalog kind
skill
Gateway key
implementation-guide
Source
github.com/rshankras/claude-code-apple-skills
Implementation Guide Skill (implementation-guide) · ahel