Scaffold iOS features with Swift/SwiftUI, Clean Architecture, MVVM, and structured concurrency
Production Swift/SwiftUI architecture. Clean Architecture with Swift Concurrency. Mirrors Android scaffold structure for cross-platform consistency.
Default: Clean Architecture + MVVM + Swift Concurrency Alternative: The Composable Architecture (TCA) — ask if user specifies TCA
Presentation Layer → SwiftUI Views + ViewModels (@Observable / ObservableObject)
Domain Layer → Use Cases + Repository Protocols (pure Swift, no frameworks)
Data Layer → Repository Impls + Data Sources (URLSession, Firebase, CoreData)
DI Layer → DIContainer or swift-dependencies (TCA)
Feature/[FeatureName]/
├── Domain/
│ ├── Models/ [FeatureName].swift ← Pure Swift value types
│ ├── Repositories/ [FeatureName]Repository.swift ← Protocol only
│ └── UseCases/ [Action][FeatureName]UseCase.swift
├── Data/
│ ├── DTOs/ [FeatureName]DTO.swift ← Codable + mapper
│ ├── DataSources/ [FeatureName]RemoteDataSource.swift
│ └── Repositories/ [FeatureName]RepositoryImpl.swift
├── Presentation/
│ ├── [FeatureName]ViewModel.swift ← @Observable or @MainActor
│ ├── [FeatureName]View.swift ← SwiftUI root view
│ ├── [FeatureName]State.swift ← State/action enums
│ └── Components/ [Component]View.swift
└── DI/
└── [FeatureName]Module.swift
Before starting, gather project context silently:
PORTFOLIO.md if it exists in the project root or parent directories for product/team contextcat package.json 2>/dev/null || cat build.gradle.kts 2>/dev/null || cat Podfile 2>/dev/null to detect stackgit log --oneline -5 2>/dev/null for recent changesls src/ app/ lib/ functions/ 2>/dev/null to understand project structure| Request | Action |
|---|---|
| Full feature scaffold | Generate all layers |
| SwiftUI view + ViewModel | Generate presentation layer |
| Data layer + networking | Generate data layer |
| StoreKit 2 subscriptions | Generate StoreKit integration |
| Firebase iOS integration | Generate Firebase data layer |
| TCA architecture | Generate TCA pattern |
| Testing scaffold | Generate XCTest files |
iOS 17+: @Observable macro (preferred)
iOS 16 and below: ObservableObject + @Published
TCA: Store<State, Action> + Reducer
async throws — never DispatchQueue or completion handlers@MainActor — annotate ViewModelsactor — never raw class with locksasync let for parallel work, TaskGroup for dynamic parallelismTask { } stored as property, cancel in deinit / .onDisappearenum [Feature]Error: LocalizedError {
case notFound(id: String)
case networkUnavailable
case unauthorized
case unknown(underlying: Error)
var errorDescription: String? {
switch self {
case .notFound(let id): return "Item \(id) not found."
case .networkUnavailable: return "No internet connection."
case .unauthorized: return "You don't have access."
case .unknown: return "An unexpected error occurred."
}
}
}
protocol [Feature]Repository {
func get(id: String) async throws -> [Feature]
func observe(id: String) -> AsyncThrowingStream<[Feature], Error>
func update(_ item: [Feature]) async throws
}
@Observable @MainActor)You MUST generate actual Swift files using the Write tool:
Domain/Models/{Feature}.swift, Domain/UseCases/{Feature}UseCase.swift, Domain/Repositories/{Feature}RepositoryProtocol.swiftData/DTOs/{Feature}DTO.swift, Data/Repositories/{Feature}Repository.swift, Data/Mappers/{Feature}Mapper.swiftPresentation/{Feature}/{Feature}ViewModel.swift, Presentation/{Feature}/{Feature}View.swiftDI/{Feature}Assembly.swiftTests/{Feature}/{Feature}ViewModelTests.swift, Tests/{Feature}/{Feature}UseCaseTests.swiftBefore generating, use Glob to find existing feature modules (**/*ViewModel.swift, **/*UseCase.swift) and match conventions.
/database-architect — for CoreData/SwiftData schema design and migrations/testing-strategy — for XCTest standards and coverage expectations/ci-cd-pipeline — for iOS Fastlane and TestFlight workflows/accessibility-audit — for SwiftUI accessibility modifiers and VoiceOver compliance