.claude/skills/add-screen/SKILL.md
Add a screen to an existing feature
npx skillsauth add adamayoung/popcorn add-screenInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Guide for adding a new screen/view to an existing TCA feature with proper navigation.
Ask the user for:
If the screen needs its own reducer, create it in the feature package:
@Reducer
public struct {ScreenName}Feature: Sendable {
@Dependency(\.{screenName}Client) private var client
@ObservableState
public struct State: Sendable {
let id: Int
var viewState: ViewState = .initial
public init(id: Int) {
self.id = id
}
}
public enum ViewState: Sendable {
case initial
case loading
case ready(ViewSnapshot)
case error(Error)
}
public enum Action: Sendable {
case didAppear
case fetch
case loaded(ViewSnapshot)
case failed(Error)
case navigate(Navigation)
}
public enum Navigation: Equatable, Hashable, Sendable {
// Define navigation destinations
}
public init() {}
public var body: some Reducer<State, Action> {
Reduce { state, action in
// Implementation
}
}
}
In the parent feature's Path reducer enum:
@Reducer
enum Path {
case existingScreen(ExistingFeature)
case {screenName}({ScreenName}Feature) // Add this
}
In the parent reducer's body:
case .existingScreen(.navigate(.{screenName}(let id))):
state.path.append(.{screenName}({ScreenName}Feature.State(id: id)))
return .none
Or if navigating from the root:
case .{rootFeature}(.navigate(.{screenName}(let id))):
state.path.append(.{screenName}({ScreenName}Feature.State(id: id)))
return .none
In the parent's view, add to the destination closure:
NavigationStack(path: $store.scope(state: \.path, action: \.path)) {
RootView(store: store.scope(state: \.root, action: \.root))
} destination: { store in
switch store.case {
case .existingScreen(let store):
ExistingView(store: store)
case .{screenName}(let store):
{ScreenName}View(store: store) // Add this
}
}
struct {ScreenName}View: View {
@Bindable var store: StoreOf<{ScreenName}Feature>
var body: some View {
// View implementation
}
}
Use SCREAMING_SNAKE_CASE keys for all user-facing strings. Build first, then add English values in Localizable.xcstrings — see SWIFTUI.md § Localization.
In the feature that triggers navigation:
public enum Navigation: Equatable, Hashable, Sendable {
case {screenName}(id: Int)
}
$ARGUMENTS
data-ai
Add properties to an existing domain model from TMDb
testing
Run all unit tests
testing
Run UI tests
testing
Run snapshot tests