Implementation Guide Skill
SkillAI & modelsGenerates 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.
No other account needed.
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:
- PRD exists (from prd-generator skill) with all features defined
- ARCHITECTURE.md exists (from architecture-spec skill) with tech stack and structure
- UX_SPEC.md exists (from ux-spec skill) with wireframes and interactions
- DESIGN_SYSTEM.md exists with colors, typography, components
Input Sources
Read and extract information from:
-
docs/PRD.md
- All features and user stories
- Acceptance criteria
- Success metrics
- Timeline estimates
-
docs/ARCHITECTURE.md
- Architecture pattern (MVVM, Clean, TCA)
- Technology stack decisions
- Data models and relationships
- Module structure
- Networking layer design
-
docs/UX_SPEC.md
- All screens and wireframes
- User flows
- Interactions and gestures
- States (empty, loading, error)
-
docs/DESIGN_SYSTEM.md
- Colors, typography, spacing
- Component styles
- Animation timings
- Design tokens
-
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
-
Open Xcode 15+
-
File → New → Project
-
Choose template: iOS → App
-
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
-
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:
- Right-click project in Navigator
- New Group (⌘⌥N)
- Name it exactly as above
- Create subgroups as needed
- 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
@Modelmacro for SwiftData (automatic persistence) - Mark unique fields with
@Attribute(.unique) - Define relationships with
@Relationship(deleteRule:inverse:) - Add validation methods for data integrity
- Use
finalfor classes that don't need subclassing (performance) - Add
Codableconformance if syncing with backend API
Repeat for all models listed in ARCHITECTURE.md:
Models/Item.swiftModels/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