ios-modular-architecture/SKILL.md
Design and implement modular iOS app architecture using Swift Packages, feature modules, and clean boundaries. Use when structuring large apps, creating feature modules, improving build times, enabling team scaling, or refactoring monoliths into modules. Triggers on modular, module, package, architecture, monolith, feature module, scalability, build time, micro-feature.
npx skillsauth add abanoub-ashraf/manus-skills-import ios-modular-architectureInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
4 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are an expert in modular iOS architecture. When this skill activates, help design and implement scalable, maintainable app structures using modules.
| Benefit | Impact | |---------|--------| | Build Time | Only rebuild changed modules (10min → 30sec) | | Testing | Test modules in isolation, faster CI | | Team Scaling | Teams own modules, fewer conflicts | | Code Reuse | Share between app, widgets, extensions | | Encapsulation | Clear APIs, hidden implementation | | Parallel Work | Multiple features developed simultaneously |
┌─────────────────────────────────────────────────────────┐
│ App Layer │
│ (Main App Target) │
└─────────────────────────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Feature A │ │ Feature B │ │ Feature C │
│ Module │ │ Module │ │ Module │
└───────────────┘ └───────────────┘ └───────────────┘
│ │ │
└───────────────────┼───────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ Shared Layer │
│ (DesignSystem, Networking, Analytics) │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Core Layer │
│ (Models, Utilities, Extensions) │
└─────────────────────────────────────────────────────────┘
MyApp/
├── App/ # Main app target
│ ├── MyApp.swift
│ ├── AppDelegate.swift
│ ├── RootCoordinator.swift
│ └── DependencyContainer.swift
│
├── Packages/ # Local Swift Packages
│ ├── Features/
│ │ ├── HomeFeature/
│ │ ├── ProfileFeature/
│ │ ├── SettingsFeature/
│ │ └── OnboardingFeature/
│ │
│ ├── Shared/
│ │ ├── DesignSystem/
│ │ ├── Networking/
│ │ ├── Analytics/
│ │ └── Authentication/
│ │
│ └── Core/
│ ├── Models/
│ ├── Utilities/
│ └── Extensions/
│
├── MyApp.xcodeproj
└── Package.swift # Workspace package (optional)
HomeFeature/
├── Package.swift
├── Sources/
│ └── HomeFeature/
│ ├── Public/ # Public API
│ │ ├── HomeFeatureAPI.swift # Protocol/Interface
│ │ └── HomeFeatureBuilder.swift
│ │
│ ├── Internal/ # Implementation
│ │ ├── Views/
│ │ │ ├── HomeView.swift
│ │ │ └── Components/
│ │ ├── ViewModels/
│ │ │ └── HomeViewModel.swift
│ │ ├── Models/
│ │ │ └── HomeItem.swift
│ │ └── Services/
│ │ └── HomeService.swift
│ │
│ └── Resources/
│ └── Localizable.xcstrings
│
└── Tests/
└── HomeFeatureTests/
├── HomeViewModelTests.swift
└── Mocks/
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "HomeFeature",
platforms: [.iOS(.v17)],
products: [
.library(
name: "HomeFeature",
targets: ["HomeFeature"]
),
// Separate target for interface (optional but recommended)
.library(
name: "HomeFeatureInterface",
targets: ["HomeFeatureInterface"]
)
],
dependencies: [
// Local packages
.package(path: "../Shared/DesignSystem"),
.package(path: "../Shared/Networking"),
.package(path: "../Core/Models"),
// External packages
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.0.0")
],
targets: [
// Interface target - only protocols and models
.target(
name: "HomeFeatureInterface",
dependencies: [
.product(name: "Models", package: "Models")
]
),
// Implementation target
.target(
name: "HomeFeature",
dependencies: [
"HomeFeatureInterface",
.product(name: "DesignSystem", package: "DesignSystem"),
.product(name: "Networking", package: "Networking"),
.product(name: "Dependencies", package: "swift-dependencies")
]
),
.testTarget(
name: "HomeFeatureTests",
dependencies: ["HomeFeature"]
)
]
)
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "Core",
platforms: [.iOS(.v17)],
products: [
.library(name: "Models", targets: ["Models"]),
.library(name: "Utilities", targets: ["Utilities"]),
.library(name: "Extensions", targets: ["Extensions"])
],
targets: [
.target(name: "Models"),
.target(name: "Utilities"),
.target(
name: "Extensions",
dependencies: ["Models"]
),
.testTarget(name: "ModelsTests", dependencies: ["Models"]),
.testTarget(name: "UtilitiesTests", dependencies: ["Utilities"])
]
)
// HomeFeatureInterface/HomeFeatureAPI.swift
import SwiftUI
import Models
public protocol HomeFeatureAPI {
associatedtype Content: View
@MainActor @ViewBuilder func homeView() -> Content
}
public protocol HomeFeatureBuilder {
func build(dependencies: HomeFeatureDependencies) -> any HomeFeatureAPI
}
public struct HomeFeatureDependencies {
public let analyticsClient: AnalyticsClient
public let apiClient: APIClient
public let userSession: UserSession
public init(
analyticsClient: AnalyticsClient,
apiClient: APIClient,
userSession: UserSession
) {
self.analyticsClient = analyticsClient
self.apiClient = apiClient
self.userSession = userSession
}
}
// HomeFeature/HomeFeatureImpl.swift
import SwiftUI
import HomeFeatureInterface
public struct HomeFeatureImpl: HomeFeatureAPI {
private let dependencies: HomeFeatureDependencies
public init(dependencies: HomeFeatureDependencies) {
self.dependencies = dependencies
}
@MainActor
public func homeView() -> some View {
HomeView(
viewModel: HomeViewModel(
apiClient: dependencies.apiClient,
analytics: dependencies.analyticsClient
)
)
}
}
// Builder
public struct HomeFeatureBuilderImpl: HomeFeatureBuilder {
public init() {}
public func build(dependencies: HomeFeatureDependencies) -> any HomeFeatureAPI {
HomeFeatureImpl(dependencies: dependencies)
}
}
// App/Coordination/AppCoordinator.swift
import SwiftUI
import HomeFeatureInterface
import ProfileFeatureInterface
@Observable
@MainActor
class AppCoordinator {
enum Destination: Hashable {
case home
case profile(userID: String)
case settings
}
var path = NavigationPath()
// Feature builders (injected)
private let homeBuilder: any HomeFeatureBuilder
private let profileBuilder: any ProfileFeatureBuilder
init(
homeBuilder: any HomeFeatureBuilder,
profileBuilder: any ProfileFeatureBuilder
) {
self.homeBuilder = homeBuilder
self.profileBuilder = profileBuilder
}
func navigate(to destination: Destination) {
path.append(destination)
}
func pop() {
path.removeLast()
}
func popToRoot() {
path.removeLast(path.count)
}
@ViewBuilder
func view(for destination: Destination) -> some View {
switch destination {
case .home:
homeBuilder.build(dependencies: makeDependencies()).homeView()
case .profile(let userID):
profileBuilder.build(dependencies: makeDependencies()).profileView(userID: userID)
case .settings:
SettingsView()
}
}
}
// Each module defines its routes
public enum HomeRoute: Hashable {
case feed
case item(id: String)
case search(query: String)
}
// Central router resolves URLs to routes
struct DeepLinkRouter {
func route(from url: URL) -> AppCoordinator.Destination? {
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
return nil
}
switch components.path {
case "/home":
return .home
case "/profile":
if let userID = components.queryItems?.first(where: { $0.name == "id" })?.value {
return .profile(userID: userID)
}
default:
break
}
return nil
}
}
✅ Allowed:
- App → Features → Shared → Core
- Feature A → FeatureAInterface (not Feature B implementation)
- Shared → Core
- Any → External packages
❌ Not Allowed:
- Core → Shared (upward dependency)
- Core → Features (upward dependency)
- Feature A → Feature B implementation (lateral without interface)
- Shared → Features (upward dependency)
# .swiftlint.yml
custom_rules:
no_feature_cross_import:
name: "No Feature Cross Import"
regex: "import \\w+Feature(?!Interface)"
message: "Features should only import other feature interfaces, not implementations"
severity: error
included: ".*Feature/Sources.*"
// Other modules depend on interface, not implementation
dependencies: [
.product(name: "HomeFeatureInterface", package: "HomeFeature"),
// NOT: .product(name: "HomeFeature", package: "HomeFeature")
]
// Only expose what's needed
public struct HomeFeatureImpl { } // Public
struct HomeViewModel { } // Internal (default)
private class HomeService { } // Private
# Xcode builds independent modules in parallel automatically
# Check with: xcodebuild -showBuildTimingSummary
// For stable modules, consider pre-building
// Using tools like Tuist or manually with xcodebuild
Core/Models with shared data typesCore/Utilities with helpersShared/NetworkingShared/Analytics// HomeFeatureTests/HomeViewModelTests.swift
import XCTest
@testable import HomeFeature
import HomeFeatureInterface
final class HomeViewModelTests: XCTestCase {
func test_loadItems_success() async {
// Given
let mockAPI = MockAPIClient()
mockAPI.itemsToReturn = [.mock]
let sut = HomeViewModel(apiClient: mockAPI)
// When
await sut.loadItems()
// Then
XCTAssertEqual(sut.items.count, 1)
}
}
// AppTests/FeatureIntegrationTests.swift
import XCTest
@testable import MyApp
import HomeFeature
import ProfileFeature
final class FeatureIntegrationTests: XCTestCase {
func test_navigateFromHomeToProfile() {
// Test navigation between real modules
}
}
development
Design principles for building polished, native-feeling SwiftUI apps and widgets. Use this skill when creating or modifying SwiftUI views, iOS widgets (WidgetKit), or any native Apple UI. Ensures proper spacing, typography, colors, and widget implementations that look and feel like quality apps rather than AI-generated slop.
data-ai
Design and implement SwiftUI views, components, and app architecture. Use when creating new SwiftUI views, implementing MVVM/TCA patterns, managing state with @Observable, @State, @Binding, or @Environment, designing navigation flows, or structuring iOS app architecture. Triggers on SwiftUI, view model, state management, navigation, coordinator pattern.
development
Implement, review, or improve SwiftUI animations and transitions. Use when adding implicit or explicit animations with withAnimation, configuring spring animations (.smooth, .snappy, .bouncy), building phase or keyframe animations with PhaseAnimator/KeyframeAnimator, creating hero transitions with matchedGeometryEffect or matchedTransitionSource, adding SF Symbol effects (bounce, pulse, variableColor, breathe, rotate, wiggle), implementing custom Transition or CustomAnimation types, or ensuring animations respect accessibilityReduceMotion.
testing
Audit SwiftUI views for accessibility (iOS + macOS) with patch-ready fixes