diff --git a/Examples/xx-messenger/Package.swift b/Examples/xx-messenger/Package.swift
index 411e8e2dcea75f6f5d6996ce29ae025403a13541..44fec1e27b0a8a9d5a0865013098b3d9bf6d189a 100644
--- a/Examples/xx-messenger/Package.swift
+++ b/Examples/xx-messenger/Package.swift
@@ -128,6 +128,7 @@ let package = Package(
     .target(
       name: "BackupFeature",
       dependencies: [
+        .target(name: "AppCore"),
         .product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
         .product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
       ],
diff --git a/Examples/xx-messenger/Sources/BackupFeature/Alerts.swift b/Examples/xx-messenger/Sources/BackupFeature/Alerts.swift
index 2bd95f770ff5ce1be9e808284d1d50f3d111af1d..e261adeba5b042c931817ffa7f0d4a6d849a2671 100644
--- a/Examples/xx-messenger/Sources/BackupFeature/Alerts.swift
+++ b/Examples/xx-messenger/Sources/BackupFeature/Alerts.swift
@@ -1,8 +1,8 @@
 import ComposableArchitecture
 
-extension AlertState where Action == BackupAction {
-  public static func error(_ error: Error) -> AlertState<BackupAction> {
-    AlertState(
+extension AlertState where Action == BackupComponent.Action {
+  public static func error(_ error: Error) -> AlertState<BackupComponent.Action> {
+    AlertState<BackupComponent.Action>(
       title: TextState("Error"),
       message: TextState(error.localizedDescription)
     )
diff --git a/Examples/xx-messenger/Sources/BackupFeature/BackupComponent.swift b/Examples/xx-messenger/Sources/BackupFeature/BackupComponent.swift
new file mode 100644
index 0000000000000000000000000000000000000000..af3e3c34a5728a73a084c307b918fab128cce7b8
--- /dev/null
+++ b/Examples/xx-messenger/Sources/BackupFeature/BackupComponent.swift
@@ -0,0 +1,209 @@
+import AppCore
+import Combine
+import ComposableArchitecture
+import Foundation
+import XXClient
+import XXMessengerClient
+
+public struct BackupComponent: ReducerProtocol {
+  public struct State: Equatable {
+    public enum Field: String, Hashable {
+      case passphrase
+    }
+
+    public enum Error: String, Swift.Error, Equatable {
+      case contactUsernameMissing
+    }
+
+    public init(
+      isRunning: Bool = false,
+      isStarting: Bool = false,
+      isResuming: Bool = false,
+      isStopping: Bool = false,
+      backup: BackupStorage.Backup? = nil,
+      alert: AlertState<Action>? = nil,
+      focusedField: Field? = nil,
+      passphrase: String = "",
+      isExporting: Bool = false,
+      exportData: Data? = nil
+    ) {
+      self.isRunning = isRunning
+      self.isStarting = isStarting
+      self.isResuming = isResuming
+      self.isStopping = isStopping
+      self.backup = backup
+      self.alert = alert
+      self.focusedField = focusedField
+      self.passphrase = passphrase
+      self.isExporting = isExporting
+      self.exportData = exportData
+    }
+
+    public var isRunning: Bool
+    public var isStarting: Bool
+    public var isResuming: Bool
+    public var isStopping: Bool
+    public var backup: BackupStorage.Backup?
+    public var alert: AlertState<Action>?
+    @BindableState public var focusedField: Field?
+    @BindableState public var passphrase: String
+    @BindableState public var isExporting: Bool
+    public var exportData: Data?
+  }
+
+  public enum Action: Equatable, BindableAction {
+    case task
+    case cancelTask
+    case startTapped
+    case resumeTapped
+    case stopTapped
+    case exportTapped
+    case alertDismissed
+    case backupUpdated(BackupStorage.Backup?)
+    case didStart(failure: NSError?)
+    case didResume(failure: NSError?)
+    case didStop(failure: NSError?)
+    case didExport(failure: NSError?)
+    case binding(BindingAction<State>)
+  }
+
+  public init() {}
+
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.backupStorage) var backupStorage: BackupStorage
+  @Dependency(\.app.mainQueue) var mainQueue: AnySchedulerOf<DispatchQueue>
+  @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue>
+
+  public var body: some ReducerProtocol<State, Action> {
+    BindingReducer()
+    Reduce { state, action in
+      enum TaskEffectId {}
+
+      switch action {
+      case .task:
+        state.isRunning = messenger.isBackupRunning()
+        return Effect.run { subscriber in
+          subscriber.send(.backupUpdated(backupStorage.stored()))
+          let cancellable = backupStorage.observe { backup in
+            subscriber.send(.backupUpdated(backup))
+          }
+          return AnyCancellable { cancellable.cancel() }
+        }
+        .subscribe(on: bgQueue)
+        .receive(on: mainQueue)
+        .eraseToEffect()
+        .cancellable(id: TaskEffectId.self, cancelInFlight: true)
+
+      case .cancelTask:
+        return .cancel(id: TaskEffectId.self)
+
+      case .startTapped:
+        state.isStarting = true
+        state.focusedField = nil
+        return Effect.run { [state] subscriber in
+          do {
+            let contact = try messenger.myContact(includeFacts: .types([.username]))
+            guard let username = try contact.getFact(.username)?.value else {
+              throw State.Error.contactUsernameMissing
+            }
+            try messenger.startBackup(
+              password: state.passphrase,
+              params: BackupParams(username: username)
+            )
+            subscriber.send(.didStart(failure: nil))
+          } catch {
+            subscriber.send(.didStart(failure: error as NSError))
+          }
+          subscriber.send(completion: .finished)
+          return AnyCancellable {}
+        }
+        .subscribe(on: bgQueue)
+        .receive(on: mainQueue)
+        .eraseToEffect()
+
+      case .resumeTapped:
+        state.isResuming = true
+        return Effect.run { subscriber in
+          do {
+            try messenger.resumeBackup()
+            subscriber.send(.didResume(failure: nil))
+          } catch {
+            subscriber.send(.didResume(failure: error as NSError))
+          }
+          subscriber.send(completion: .finished)
+          return AnyCancellable {}
+        }
+        .subscribe(on: bgQueue)
+        .receive(on: mainQueue)
+        .eraseToEffect()
+
+      case .stopTapped:
+        state.isStopping = true
+        return Effect.run { subscriber in
+          do {
+            try messenger.stopBackup()
+            try backupStorage.remove()
+            subscriber.send(.didStop(failure: nil))
+          } catch {
+            subscriber.send(.didStop(failure: error as NSError))
+          }
+          subscriber.send(completion: .finished)
+          return AnyCancellable {}
+        }
+        .subscribe(on: bgQueue)
+        .receive(on: mainQueue)
+        .eraseToEffect()
+
+      case .exportTapped:
+        state.isExporting = true
+        state.exportData = state.backup?.data
+        return .none
+
+      case .alertDismissed:
+        state.alert = nil
+        return .none
+
+      case .backupUpdated(let backup):
+        state.backup = backup
+        return .none
+
+      case .didStart(let failure):
+        state.isRunning = messenger.isBackupRunning()
+        state.isStarting = false
+        if let failure {
+          state.alert = .error(failure)
+        } else {
+          state.passphrase = ""
+        }
+        return .none
+
+      case .didResume(let failure):
+        state.isRunning = messenger.isBackupRunning()
+        state.isResuming = false
+        if let failure {
+          state.alert = .error(failure)
+        }
+        return .none
+
+      case .didStop(let failure):
+        state.isRunning = messenger.isBackupRunning()
+        state.isStopping = false
+        if let failure {
+          state.alert = .error(failure)
+        }
+        return .none
+
+      case .didExport(let failure):
+        state.isExporting = false
+        state.exportData = nil
+        if let failure {
+          state.alert = .error(failure)
+        }
+        return .none
+
+      case .binding(_):
+        return .none
+      }
+    }
+  }
+}
diff --git a/Examples/xx-messenger/Sources/BackupFeature/BackupFeature.swift b/Examples/xx-messenger/Sources/BackupFeature/BackupFeature.swift
deleted file mode 100644
index 8010f17d1d0727c4621841dd124a93dcda0e0b5d..0000000000000000000000000000000000000000
--- a/Examples/xx-messenger/Sources/BackupFeature/BackupFeature.swift
+++ /dev/null
@@ -1,228 +0,0 @@
-import Combine
-import ComposableArchitecture
-import Foundation
-import XXClient
-import XXMessengerClient
-
-public struct BackupState: Equatable {
-  public enum Field: String, Hashable {
-    case passphrase
-  }
-
-  public enum Error: String, Swift.Error, Equatable {
-    case contactUsernameMissing
-  }
-
-  public init(
-    isRunning: Bool = false,
-    isStarting: Bool = false,
-    isResuming: Bool = false,
-    isStopping: Bool = false,
-    backup: BackupStorage.Backup? = nil,
-    alert: AlertState<BackupAction>? = nil,
-    focusedField: Field? = nil,
-    passphrase: String = "",
-    isExporting: Bool = false,
-    exportData: Data? = nil
-  ) {
-    self.isRunning = isRunning
-    self.isStarting = isStarting
-    self.isResuming = isResuming
-    self.isStopping = isStopping
-    self.backup = backup
-    self.alert = alert
-    self.focusedField = focusedField
-    self.passphrase = passphrase
-    self.isExporting = isExporting
-    self.exportData = exportData
-  }
-
-  public var isRunning: Bool
-  public var isStarting: Bool
-  public var isResuming: Bool
-  public var isStopping: Bool
-  public var backup: BackupStorage.Backup?
-  public var alert: AlertState<BackupAction>?
-  @BindableState public var focusedField: Field?
-  @BindableState public var passphrase: String
-  @BindableState public var isExporting: Bool
-  public var exportData: Data?
-}
-
-public enum BackupAction: Equatable, BindableAction {
-  case task
-  case cancelTask
-  case startTapped
-  case resumeTapped
-  case stopTapped
-  case exportTapped
-  case alertDismissed
-  case backupUpdated(BackupStorage.Backup?)
-  case didStart(failure: NSError?)
-  case didResume(failure: NSError?)
-  case didStop(failure: NSError?)
-  case didExport(failure: NSError?)
-  case binding(BindingAction<BackupState>)
-}
-
-public struct BackupEnvironment {
-  public init(
-    messenger: Messenger,
-    backupStorage: BackupStorage,
-    mainQueue: AnySchedulerOf<DispatchQueue>,
-    bgQueue: AnySchedulerOf<DispatchQueue>
-  ) {
-    self.messenger = messenger
-    self.backupStorage = backupStorage
-    self.mainQueue = mainQueue
-    self.bgQueue = bgQueue
-  }
-
-  public var messenger: Messenger
-  public var backupStorage: BackupStorage
-  public var mainQueue: AnySchedulerOf<DispatchQueue>
-  public var bgQueue: AnySchedulerOf<DispatchQueue>
-}
-
-#if DEBUG
-extension BackupEnvironment {
-  public static let unimplemented = BackupEnvironment(
-    messenger: .unimplemented,
-    backupStorage: .unimplemented,
-    mainQueue: .unimplemented,
-    bgQueue: .unimplemented
-  )
-}
-#endif
-
-public let backupReducer = Reducer<BackupState, BackupAction, BackupEnvironment>
-{ state, action, env in
-  enum TaskEffectId {}
-
-  switch action {
-  case .task:
-    state.isRunning = env.messenger.isBackupRunning()
-    return Effect.run { subscriber in
-      subscriber.send(.backupUpdated(env.backupStorage.stored()))
-      let cancellable = env.backupStorage.observe { backup in
-        subscriber.send(.backupUpdated(backup))
-      }
-      return AnyCancellable { cancellable.cancel() }
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-    .cancellable(id: TaskEffectId.self, cancelInFlight: true)
-
-  case .cancelTask:
-    return .cancel(id: TaskEffectId.self)
-
-  case .startTapped:
-    state.isStarting = true
-    state.focusedField = nil
-    return Effect.run { [state] subscriber in
-      do {
-        let contact = try env.messenger.myContact(includeFacts: .types([.username]))
-        guard let username = try contact.getFact(.username)?.value else {
-          throw BackupState.Error.contactUsernameMissing
-        }
-        try env.messenger.startBackup(
-          password: state.passphrase,
-          params: BackupParams(username: username)
-        )
-        subscriber.send(.didStart(failure: nil))
-      } catch {
-        subscriber.send(.didStart(failure: error as NSError))
-      }
-      subscriber.send(completion: .finished)
-      return AnyCancellable {}
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-
-  case .resumeTapped:
-    state.isResuming = true
-    return Effect.run { subscriber in
-      do {
-        try env.messenger.resumeBackup()
-        subscriber.send(.didResume(failure: nil))
-      } catch {
-        subscriber.send(.didResume(failure: error as NSError))
-      }
-      subscriber.send(completion: .finished)
-      return AnyCancellable {}
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-
-  case .stopTapped:
-    state.isStopping = true
-    return Effect.run { subscriber in
-      do {
-        try env.messenger.stopBackup()
-        try env.backupStorage.remove()
-        subscriber.send(.didStop(failure: nil))
-      } catch {
-        subscriber.send(.didStop(failure: error as NSError))
-      }
-      subscriber.send(completion: .finished)
-      return AnyCancellable {}
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-
-  case .exportTapped:
-    state.isExporting = true
-    state.exportData = state.backup?.data
-    return .none
-
-  case .alertDismissed:
-    state.alert = nil
-    return .none
-
-  case .backupUpdated(let backup):
-    state.backup = backup
-    return .none
-
-  case .didStart(let failure):
-    state.isRunning = env.messenger.isBackupRunning()
-    state.isStarting = false
-    if let failure {
-      state.alert = .error(failure)
-    } else {
-      state.passphrase = ""
-    }
-    return .none
-
-  case .didResume(let failure):
-    state.isRunning = env.messenger.isBackupRunning()
-    state.isResuming = false
-    if let failure {
-      state.alert = .error(failure)
-    }
-    return .none
-
-  case .didStop(let failure):
-    state.isRunning = env.messenger.isBackupRunning()
-    state.isStopping = false
-    if let failure {
-      state.alert = .error(failure)
-    }
-    return .none
-
-  case .didExport(let failure):
-    state.isExporting = false
-    state.exportData = nil
-    if let failure {
-      state.alert = .error(failure)
-    }
-    return .none
-
-  case .binding(_):
-    return .none
-  }
-}
-.binding()
diff --git a/Examples/xx-messenger/Sources/BackupFeature/BackupView.swift b/Examples/xx-messenger/Sources/BackupFeature/BackupView.swift
index 89510b2fbf2c993afa1438fd62408dc925d1c30e..78805e66acd18a8200d461f803243673d509bdac 100644
--- a/Examples/xx-messenger/Sources/BackupFeature/BackupView.swift
+++ b/Examples/xx-messenger/Sources/BackupFeature/BackupView.swift
@@ -3,12 +3,12 @@ import SwiftUI
 import UniformTypeIdentifiers
 
 public struct BackupView: View {
-  public init(store: Store<BackupState, BackupAction>) {
+  public init(store: StoreOf<BackupComponent>) {
     self.store = store
   }
 
-  let store: Store<BackupState, BackupAction>
-  @FocusState var focusedField: BackupState.Field?
+  let store: StoreOf<BackupComponent>
+  @FocusState var focusedField: BackupComponent.State.Field?
 
   struct ViewState: Equatable {
     struct Backup: Equatable {
@@ -16,7 +16,7 @@ public struct BackupView: View {
       var size: Int
     }
 
-    init(state: BackupState) {
+    init(state: BackupComponent.State) {
       isRunning = state.isRunning
       isStarting = state.isStarting
       isResuming = state.isResuming
@@ -36,7 +36,7 @@ public struct BackupView: View {
     var isStopping: Bool
     var isLoading: Bool { isStarting || isResuming || isStopping }
     var backup: Backup?
-    var focusedField: BackupState.Field?
+    var focusedField: BackupComponent.State.Field?
     var passphrase: String
     var isExporting: Bool
     var exportData: Data?
@@ -67,7 +67,7 @@ public struct BackupView: View {
   }
 
   @ViewBuilder func newBackupSection(
-    _ viewStore: ViewStore<ViewState, BackupAction>
+    _ viewStore: ViewStore<ViewState, BackupComponent.Action>
   ) -> some View {
     Section {
       SecureField(
@@ -103,7 +103,7 @@ public struct BackupView: View {
   }
 
   @ViewBuilder func backupSection(
-    _ viewStore: ViewStore<ViewState, BackupAction>
+    _ viewStore: ViewStore<ViewState, BackupComponent.Action>
   ) -> some View {
     Section {
       backupView(viewStore)
@@ -115,7 +115,7 @@ public struct BackupView: View {
   }
 
   @ViewBuilder func backupView(
-    _ viewStore: ViewStore<ViewState, BackupAction>
+    _ viewStore: ViewStore<ViewState, BackupComponent.Action>
   ) -> some View {
     if let backup = viewStore.backup {
       HStack {
@@ -165,7 +165,7 @@ public struct BackupView: View {
   }
 
   @ViewBuilder func stopView(
-    _ viewStore: ViewStore<ViewState, BackupAction>
+    _ viewStore: ViewStore<ViewState, BackupComponent.Action>
   ) -> some View {
     if viewStore.isRunning {
       Button {
@@ -185,7 +185,7 @@ public struct BackupView: View {
   }
 
   @ViewBuilder func resumeView(
-    _ viewStore: ViewStore<ViewState, BackupAction>
+    _ viewStore: ViewStore<ViewState, BackupComponent.Action>
   ) -> some View {
     if !viewStore.isRunning, viewStore.backup != nil {
       Button {
@@ -240,9 +240,8 @@ public struct BackupView_Previews: PreviewProvider {
   public static var previews: some View {
     NavigationView {
       BackupView(store: Store(
-        initialState: BackupState(),
-        reducer: .empty,
-        environment: ()
+        initialState: BackupComponent.State(),
+        reducer: EmptyReducer()
       ))
     }
   }
diff --git a/Examples/xx-messenger/Tests/BackupFeatureTests/BackupFeatureTests.swift b/Examples/xx-messenger/Tests/BackupFeatureTests/BackupComponentTests.swift
similarity index 70%
rename from Examples/xx-messenger/Tests/BackupFeatureTests/BackupFeatureTests.swift
rename to Examples/xx-messenger/Tests/BackupFeatureTests/BackupComponentTests.swift
index d0c69eb87e2efea29f635fce84656b04d2e35cba..e409a1b9241f2a342f77fc3dca23174ca06c1c15 100644
--- a/Examples/xx-messenger/Tests/BackupFeatureTests/BackupFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/BackupFeatureTests/BackupComponentTests.swift
@@ -14,19 +14,18 @@ final class BackupFeatureTests: XCTestCase {
     )
 
     let store = TestStore(
-      initialState: BackupState(),
-      reducer: backupReducer,
-      environment: .unimplemented
+      initialState: BackupComponent.State(),
+      reducer: BackupComponent()
     )
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.isBackupRunning.run = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.isBackupRunning.run = {
       isBackupRunning.removeFirst()
     }
-    store.environment.backupStorage.stored = {
+    store.dependencies.app.backupStorage.stored = {
       storedBackup
     }
-    store.environment.backupStorage.observe = {
+    store.dependencies.app.backupStorage.observe = {
       let id = UUID()
       observers[id] = $0
       return Cancellable { observers[id] = nil }
@@ -68,22 +67,21 @@ final class BackupFeatureTests: XCTestCase {
     let passphrase = "backup-password"
 
     let store = TestStore(
-      initialState: BackupState(),
-      reducer: backupReducer,
-      environment: .unimplemented
+      initialState: BackupComponent.State(),
+      reducer: BackupComponent()
     )
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.myContact.run = { includeFacts in
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.myContact.run = { includeFacts in
       actions.append(.didGetMyContact(includingFacts: includeFacts))
       var contact = Contact.unimplemented("contact-data".data(using: .utf8)!)
       contact.getFactsFromContact.run = { _ in [Fact(type: .username, value: username)] }
       return contact
     }
-    store.environment.messenger.startBackup.run = { passphrase, params in
+    store.dependencies.app.messenger.startBackup.run = { passphrase, params in
       actions.append(.didStartBackup(passphrase: passphrase, params: params))
     }
-    store.environment.messenger.isBackupRunning.run = {
+    store.dependencies.app.messenger.isBackupRunning.run = {
       isBackupRunning.removeFirst()
     }
 
@@ -124,20 +122,19 @@ final class BackupFeatureTests: XCTestCase {
     var isBackupRunning: [Bool] = [false]
 
     let store = TestStore(
-      initialState: BackupState(
+      initialState: BackupComponent.State(
         passphrase: "1234"
       ),
-      reducer: backupReducer,
-      environment: .unimplemented
+      reducer: BackupComponent()
     )
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.myContact.run = { _ in
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.myContact.run = { _ in
       var contact = Contact.unimplemented("contact-data".data(using: .utf8)!)
       contact.getFactsFromContact.run = { _ in [] }
       return contact
     }
-    store.environment.messenger.isBackupRunning.run = {
+    store.dependencies.app.messenger.isBackupRunning.run = {
       isBackupRunning.removeFirst()
     }
 
@@ -145,7 +142,7 @@ final class BackupFeatureTests: XCTestCase {
       $0.isStarting = true
     }
 
-    let failure = BackupState.Error.contactUsernameMissing
+    let failure = BackupComponent.State.Error.contactUsernameMissing
     store.receive(.didStart(failure: failure as NSError)) {
       $0.isRunning = false
       $0.isStarting = false
@@ -159,16 +156,15 @@ final class BackupFeatureTests: XCTestCase {
     var isBackupRunning: [Bool] = [false]
 
     let store = TestStore(
-      initialState: BackupState(
+      initialState: BackupComponent.State(
         passphrase: "1234"
       ),
-      reducer: backupReducer,
-      environment: .unimplemented
+      reducer: BackupComponent()
     )
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.myContact.run = { _ in throw failure }
-    store.environment.messenger.isBackupRunning.run = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.myContact.run = { _ in throw failure }
+    store.dependencies.app.messenger.isBackupRunning.run = {
       isBackupRunning.removeFirst()
     }
 
@@ -189,23 +185,22 @@ final class BackupFeatureTests: XCTestCase {
     var isBackupRunning: [Bool] = [false]
 
     let store = TestStore(
-      initialState: BackupState(
+      initialState: BackupComponent.State(
         passphrase: "1234"
       ),
-      reducer: backupReducer,
-      environment: .unimplemented
+      reducer: BackupComponent()
     )
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.myContact.run = { _ in
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.myContact.run = { _ in
       var contact = Contact.unimplemented("data".data(using: .utf8)!)
       contact.getFactsFromContact.run = { _ in [Fact(type: .username, value: "username")] }
       return contact
     }
-    store.environment.messenger.startBackup.run = { _, _ in
+    store.dependencies.app.messenger.startBackup.run = { _, _ in
       throw failure
     }
-    store.environment.messenger.isBackupRunning.run = {
+    store.dependencies.app.messenger.isBackupRunning.run = {
       isBackupRunning.removeFirst()
     }
 
@@ -225,16 +220,15 @@ final class BackupFeatureTests: XCTestCase {
     var isBackupRunning: [Bool] = [true]
 
     let store = TestStore(
-      initialState: BackupState(),
-      reducer: backupReducer,
-      environment: .unimplemented
+      initialState: BackupComponent.State(),
+      reducer: BackupComponent()
     )
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.resumeBackup.run = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.resumeBackup.run = {
       actions.append(.didResumeBackup)
     }
-    store.environment.messenger.isBackupRunning.run = {
+    store.dependencies.app.messenger.isBackupRunning.run = {
       isBackupRunning.removeFirst()
     }
 
@@ -260,16 +254,15 @@ final class BackupFeatureTests: XCTestCase {
     var isBackupRunning: [Bool] = [false]
 
     let store = TestStore(
-      initialState: BackupState(),
-      reducer: backupReducer,
-      environment: .unimplemented
+      initialState: BackupComponent.State(),
+      reducer: BackupComponent()
     )
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.resumeBackup.run = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.resumeBackup.run = {
       throw failure
     }
-    store.environment.messenger.isBackupRunning.run = {
+    store.dependencies.app.messenger.isBackupRunning.run = {
       isBackupRunning.removeFirst()
     }
 
@@ -289,19 +282,18 @@ final class BackupFeatureTests: XCTestCase {
     var isBackupRunning: [Bool] = [false]
 
     let store = TestStore(
-      initialState: BackupState(),
-      reducer: backupReducer,
-      environment: .unimplemented
+      initialState: BackupComponent.State(),
+      reducer: BackupComponent()
     )
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.stopBackup.run = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.stopBackup.run = {
       actions.append(.didStopBackup)
     }
-    store.environment.messenger.isBackupRunning.run = {
+    store.dependencies.app.messenger.isBackupRunning.run = {
       isBackupRunning.removeFirst()
     }
-    store.environment.backupStorage.remove = {
+    store.dependencies.app.backupStorage.remove = {
       actions.append(.didRemoveBackup)
     }
 
@@ -330,16 +322,15 @@ final class BackupFeatureTests: XCTestCase {
     var isBackupRunning: [Bool] = [true]
 
     let store = TestStore(
-      initialState: BackupState(),
-      reducer: backupReducer,
-      environment: .unimplemented
+      initialState: BackupComponent.State(),
+      reducer: BackupComponent()
     )
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.stopBackup.run = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.stopBackup.run = {
       throw failure
     }
-    store.environment.messenger.isBackupRunning.run = {
+    store.dependencies.app.messenger.isBackupRunning.run = {
       isBackupRunning.removeFirst()
     }
 
@@ -356,11 +347,10 @@ final class BackupFeatureTests: XCTestCase {
 
   func testAlertDismissed() {
     let store = TestStore(
-      initialState: BackupState(
+      initialState: BackupComponent.State(
         alert: .error(NSError(domain: "test", code: 0))
       ),
-      reducer: backupReducer,
-      environment: .unimplemented
+      reducer: BackupComponent()
     )
 
     store.send(.alertDismissed) {
@@ -372,14 +362,13 @@ final class BackupFeatureTests: XCTestCase {
     let backupData = "backup-data".data(using: .utf8)!
 
     let store = TestStore(
-      initialState: BackupState(
+      initialState: BackupComponent.State(
         backup: .init(
           date: Date(),
           data: backupData
         )
       ),
-      reducer: backupReducer,
-      environment: .unimplemented
+      reducer: BackupComponent()
     )
 
     store.send(.exportTapped) {