Tca architect
AI agent skills
npx -y skills add ninjaproger/skills --skill tca-architectAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Architect modular iOS apps using Swift Package Manager and The Composable Architecture (TCA). Use when designing or implementing a new iOS app (or feature module) that should be split into separate SPM packages, each owning a TCA feature reducer, view, and tests. Covers the full workflow: module decomposition, Package.swift dependency graph, reducer/view/navigation patterns, dependency injection via swift-dependencies, and the delegate action pattern for cross-module communication. Trigger when the user asks to: architect a TCA app, create a new SPM module/feature, set up a modular iOS project, add a feature to an existing TCA app, wire navigation between features, or design a dependency client.
SKILL.md
6.6 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it
TCA + SPM Modular Architecture
Project Layout
MyApp/
├── MyApp/ # Xcode app target — THIN HOST ONLY (~16 lines)
│ └── MyApp.swift # @main — creates one Store, renders root view
└── MyAppKit/ # Single SPM package containing ALL code
├── Package.swift
├── Sources/
│ ├── AppCore/ # Root reducer + root view, composes all tab features
│ ├── DesignSystem/ # Tokens, colors, fonts — no TCA dependency
│ ├── Models/ # Pure Swift value types — no TCA, no UI
│ ├── Services/ # Dependency clients + actors — no UI
│ ├── <SharedComponent>/ # Reusable TCA reducer used by 2+ features (Quiz, ChapterStep…)
│ └── <Feature>/ # One module per tab/top-level feature
│ └── Resources/ # JSON, images owned by this module (.process("Resources"))
└── Tests/
└── <Feature>Tests/
Rules:
- The Xcode target never contains business logic. All code lives in the SPM package.
- No file header comments — files start directly with
importstatements. - Each module that owns static resources (
Resources/) must expose a public<Module>Bundle.swiftwithpublic static let bundle = Bundle.moduleso sibling modules can access those resources without a circular dependency.
Workflow
- Decompose features → Read
references/module-design.md - Set up Package.swift → Read
references/module-design.md(Package.swift section) - Implement reducers/views/navigation → Read
references/tca-patterns.md - Define dependency clients → Read
references/dependency-patterns.md - Wire root AppCore → See App Entry Point below
App Entry Point
// MyApp/MyAppApp.swift
import ComposableArchitecture
import AppCore
import SwiftUI
@main
struct MyApp: App {
let store = Store(initialState: AppCoreReducer.State()) {
AppCoreReducer()
}
var body: some Scene {
WindowGroup { AppCoreView(store: store) }
}
}
AppCore (Root Reducer + TabView)
AppCore imports every tab feature and composes them with Scope. The Reduce block at the end handles cross-feature logic by intercepting child delegate actions.
// Sources/AppCore/AppCoreView.swift
@Reducer
public struct AppCoreReducer {
public enum Tab: Hashable { case home, profile, settings }
@ObservableState
public struct State: Equatable {
var selectedTab: Tab = .home
var home = HomeReducer.State()
var profile = ProfileReducer.State()
var settings = SettingsReducer.State()
public init() {}
}
public enum Action {
case selectedTabChanged(Tab)
case home(HomeReducer.Action)
case profile(ProfileReducer.Action)
case settings(SettingsReducer.Action)
}
public var body: some ReducerOf<Self> {
Scope(state: \.home, action: \.home) { HomeReducer() }
Scope(state: \.profile, action: \.profile) { ProfileReducer() }
Scope(state: \.settings, action: \.settings) { SettingsReducer() }
Reduce { state, action in
switch action {
case .selectedTabChanged(let tab):
state.selectedTab = tab; return .none
case .settings(.delegate(.loggedOut)):
state.selectedTab = .home; return .none
case .home, .profile, .settings:
return .none
}
}
}
}
public struct AppCoreView: View {
@Bindable var store: StoreOf<AppCoreReducer>
public var body: some View {
TabView(selection: $store.selectedTab.sending(\.selectedTabChanged)) {
NavigationStack {
HomeView(store: store.scope(state: \.home, action: \.home))
}
.tabItem { Label("Home", systemImage: "house") }
.tag(AppCoreReducer.Tab.home)
// … other tabs
}
}
}
Key Principles
@ObservableStateon everyState— enables directstore.propertyreads in SwiftUI@Bindable var storein views — enables two-way$store.fieldbindingsScopebeforeReduce— child reducers always run before parent logic- Delegate actions for child→parent communication — see
references/tca-patterns.md @Reducer enum Destinationfor push/sheet/alert navigation — seereferences/tca-patterns.md- Dual
@Presentsfor overlay + navigation simultaneously — seereferences/tca-patterns.md @DependencyClientor manual struct for services — seereferences/dependency-patterns.md- Shared Component modules for reusable TCA reducers (used by 2+ features) — see
references/module-design.md - Bundle parameter when a child reducer loads resources from a parent module's
Resources/— seereferences/tca-patterns.md
Non-Negotiable Defaults
UI: Vanilla SwiftUI always. Use UIViewRepresentable only when SwiftUI has no equivalent (e.g. MKMapView, WKWebView, MTKView). Never wrap a UIKit component just for styling convenience.
Concurrency (in priority order):
async/await+AsyncStream+ Swift actors — always try this first- Combine — only if the API you're wrapping only exposes a
Publisherand no async equivalent exists - GCD /
NSLock/DispatchQueue— only as a last resort for legacy C/ObjC callback-only APIs
Reference Files
references/module-design.md— Module decomposition guide, Package.swift templates, dependency graph rules, shared bundle access patternreferences/tca-patterns.md— Full reducer pattern, navigation (Destination enum + @Presents), delegate actions, async effects, testingreferences/dependency-patterns.md—@DependencyClientmacro pattern, manual struct pattern, actor-as-dependency, live/test/mock implementations
What ships with it: 3 files
37.5 KB alongside SKILL.md
references/
- dependency-patterns.md11.2 KB
- module-design.md9.1 KB
- tca-patterns.md17.1 KB