diff --git a/Examples/xx-messenger/Sources/MyContactFeature/Alerts.swift b/Examples/xx-messenger/Sources/MyContactFeature/Alerts.swift
index 321139aec18ce7ae51b9be8097878a9133798236..f8693f17cc18c8f13c4412b1f30c8aac1a3c3d62 100644
--- a/Examples/xx-messenger/Sources/MyContactFeature/Alerts.swift
+++ b/Examples/xx-messenger/Sources/MyContactFeature/Alerts.swift
@@ -1,8 +1,8 @@
 import ComposableArchitecture
 
 extension AlertState {
-  public static func error(_ message: String) -> AlertState<MyContactAction> {
-    AlertState<MyContactAction>(
+  public static func error(_ message: String) -> AlertState<MyContactComponent.Action> {
+    AlertState<MyContactComponent.Action>(
       title: TextState("Error"),
       message: TextState(message),
       buttons: []
diff --git a/Examples/xx-messenger/Sources/MyContactFeature/MyContactComponent.swift b/Examples/xx-messenger/Sources/MyContactFeature/MyContactComponent.swift
new file mode 100644
index 0000000000000000000000000000000000000000..377e824b807d50e056bfd5b4826585e8fde6f6b9
--- /dev/null
+++ b/Examples/xx-messenger/Sources/MyContactFeature/MyContactComponent.swift
@@ -0,0 +1,297 @@
+import AppCore
+import Combine
+import ComposableArchitecture
+import Foundation
+import XCTestDynamicOverlay
+import XXClient
+import XXMessengerClient
+import XXModels
+
+public struct MyContactComponent: ReducerProtocol {
+  public struct State: Equatable {
+    public enum Field: String, Hashable {
+      case email
+      case emailCode
+      case phone
+      case phoneCode
+    }
+
+    public init(
+      contact: XXModels.Contact? = nil,
+      focusedField: Field? = nil,
+      email: String = "",
+      emailConfirmationID: String? = nil,
+      emailConfirmationCode: String = "",
+      isRegisteringEmail: Bool = false,
+      isConfirmingEmail: Bool = false,
+      isUnregisteringEmail: Bool = false,
+      phone: String = "",
+      phoneConfirmationID: String? = nil,
+      phoneConfirmationCode: String = "",
+      isRegisteringPhone: Bool = false,
+      isConfirmingPhone: Bool = false,
+      isUnregisteringPhone: Bool = false,
+      isLoadingFacts: Bool = false,
+      alert: AlertState<Action>? = nil
+    ) {
+      self.contact = contact
+      self.focusedField = focusedField
+      self.email = email
+      self.emailConfirmationID = emailConfirmationID
+      self.emailConfirmationCode = emailConfirmationCode
+      self.isRegisteringEmail = isRegisteringEmail
+      self.isConfirmingEmail = isConfirmingEmail
+      self.isUnregisteringEmail = isUnregisteringEmail
+      self.phone = phone
+      self.phoneConfirmationID = phoneConfirmationID
+      self.phoneConfirmationCode = phoneConfirmationCode
+      self.isRegisteringPhone = isRegisteringPhone
+      self.isConfirmingPhone = isConfirmingPhone
+      self.isUnregisteringPhone = isUnregisteringPhone
+      self.isLoadingFacts = isLoadingFacts
+      self.alert = alert
+    }
+
+    public var contact: XXModels.Contact?
+    @BindableState public var focusedField: Field?
+    @BindableState public var email: String
+    @BindableState public var emailConfirmationID: String?
+    @BindableState public var emailConfirmationCode: String
+    @BindableState public var isRegisteringEmail: Bool
+    @BindableState public var isConfirmingEmail: Bool
+    @BindableState public var isUnregisteringEmail: Bool
+    @BindableState public var phone: String
+    @BindableState public var phoneConfirmationID: String?
+    @BindableState public var phoneConfirmationCode: String
+    @BindableState public var isRegisteringPhone: Bool
+    @BindableState public var isConfirmingPhone: Bool
+    @BindableState public var isUnregisteringPhone: Bool
+    @BindableState public var isLoadingFacts: Bool
+    public var alert: AlertState<Action>?
+  }
+
+  public enum Action: Equatable, BindableAction {
+    case start
+    case contactFetched(XXModels.Contact?)
+    case registerEmailTapped
+    case confirmEmailTapped
+    case unregisterEmailTapped
+    case registerPhoneTapped
+    case confirmPhoneTapped
+    case unregisterPhoneTapped
+    case loadFactsTapped
+    case didFail(String)
+    case alertDismissed
+    case binding(BindingAction<State>)
+  }
+
+  public init() {}
+
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.dbManager.getDB) var db: DBManagerGetDB
+  @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 DBFetchEffectID {}
+      let db = self.db
+
+      switch action {
+      case .start:
+        return Effect
+          .catching { try messenger.e2e.tryGet().getContact().getId() }
+          .tryMap { try db().fetchContactsPublisher(.init(id: [$0])) }
+          .flatMap { $0 }
+          .assertNoFailure()
+          .map(\.first)
+          .map(Action.contactFetched)
+          .subscribe(on: bgQueue)
+          .receive(on: mainQueue)
+          .eraseToEffect()
+          .cancellable(id: DBFetchEffectID.self, cancelInFlight: true)
+
+      case .contactFetched(let contact):
+        state.contact = contact
+        return .none
+
+      case .registerEmailTapped:
+        state.focusedField = nil
+        state.isRegisteringEmail = true
+        return Effect.run { [state] subscriber in
+          do {
+            let ud = try messenger.ud.tryGet()
+            let fact = Fact(type: .email, value: state.email)
+            let confirmationID = try ud.sendRegisterFact(fact)
+            subscriber.send(.set(\.$emailConfirmationID, confirmationID))
+          } catch {
+            subscriber.send(.didFail(error.localizedDescription))
+          }
+          subscriber.send(.set(\.$isRegisteringEmail, false))
+          subscriber.send(completion: .finished)
+          return AnyCancellable {}
+        }
+        .subscribe(on: bgQueue)
+        .receive(on: mainQueue)
+        .eraseToEffect()
+
+      case .confirmEmailTapped:
+        guard let confirmationID = state.emailConfirmationID else { return .none }
+        state.focusedField = nil
+        state.isConfirmingEmail = true
+        return Effect.run { [state] subscriber in
+          do {
+            let ud = try messenger.ud.tryGet()
+            try ud.confirmFact(confirmationId: confirmationID, code: state.emailConfirmationCode)
+            let contactId = try messenger.e2e.tryGet().getContact().getId()
+            if var dbContact = try db().fetchContacts(.init(id: [contactId])).first {
+              dbContact.email = state.email
+              try db().saveContact(dbContact)
+            }
+            subscriber.send(.set(\.$email, ""))
+            subscriber.send(.set(\.$emailConfirmationID, nil))
+            subscriber.send(.set(\.$emailConfirmationCode, ""))
+          } catch {
+            subscriber.send(.didFail(error.localizedDescription))
+          }
+          subscriber.send(.set(\.$isConfirmingEmail, false))
+          subscriber.send(completion: .finished)
+          return AnyCancellable {}
+        }
+        .subscribe(on: bgQueue)
+        .receive(on: mainQueue)
+        .eraseToEffect()
+
+      case .unregisterEmailTapped:
+        guard let email = state.contact?.email else { return .none }
+        state.isUnregisteringEmail = true
+        return Effect.run { subscriber in
+          do {
+            let ud: UserDiscovery = try messenger.ud.tryGet()
+            let fact = Fact(type: .email, value: email)
+            try ud.removeFact(fact)
+            let contactId = try messenger.e2e.tryGet().getContact().getId()
+            if var dbContact = try db().fetchContacts(.init(id: [contactId])).first {
+              dbContact.email = nil
+              try db().saveContact(dbContact)
+            }
+          } catch {
+            subscriber.send(.didFail(error.localizedDescription))
+          }
+          subscriber.send(.set(\.$isUnregisteringEmail, false))
+          subscriber.send(completion: .finished)
+          return AnyCancellable {}
+        }
+        .subscribe(on: bgQueue)
+        .receive(on: mainQueue)
+        .eraseToEffect()
+
+      case .registerPhoneTapped:
+        state.focusedField = nil
+        state.isRegisteringPhone = true
+        return Effect.run { [state] subscriber in
+          do {
+            let ud = try messenger.ud.tryGet()
+            let fact = Fact(type: .phone, value: state.phone)
+            let confirmationID = try ud.sendRegisterFact(fact)
+            subscriber.send(.set(\.$phoneConfirmationID, confirmationID))
+          } catch {
+            subscriber.send(.didFail(error.localizedDescription))
+          }
+          subscriber.send(.set(\.$isRegisteringPhone, false))
+          subscriber.send(completion: .finished)
+          return AnyCancellable {}
+        }
+        .subscribe(on: bgQueue)
+        .receive(on: mainQueue)
+        .eraseToEffect()
+
+      case .confirmPhoneTapped:
+        guard let confirmationID = state.phoneConfirmationID else { return .none }
+        state.focusedField = nil
+        state.isConfirmingPhone = true
+        return Effect.run { [state] subscriber in
+          do {
+            let ud = try messenger.ud.tryGet()
+            try ud.confirmFact(confirmationId: confirmationID, code: state.phoneConfirmationCode)
+            let contactId = try messenger.e2e.tryGet().getContact().getId()
+            if var dbContact = try db().fetchContacts(.init(id: [contactId])).first {
+              dbContact.phone = state.phone
+              try db().saveContact(dbContact)
+            }
+            subscriber.send(.set(\.$phone, ""))
+            subscriber.send(.set(\.$phoneConfirmationID, nil))
+            subscriber.send(.set(\.$phoneConfirmationCode, ""))
+          } catch {
+            subscriber.send(.didFail(error.localizedDescription))
+          }
+          subscriber.send(.set(\.$isConfirmingPhone, false))
+          subscriber.send(completion: .finished)
+          return AnyCancellable {}
+        }
+        .subscribe(on: bgQueue)
+        .receive(on: mainQueue)
+        .eraseToEffect()
+
+      case .unregisterPhoneTapped:
+        guard let phone = state.contact?.phone else { return .none }
+        state.isUnregisteringPhone = true
+        return Effect.run { subscriber in
+          do {
+            let ud: UserDiscovery = try messenger.ud.tryGet()
+            let fact = Fact(type: .phone, value: phone)
+            try ud.removeFact(fact)
+            let contactId = try messenger.e2e.tryGet().getContact().getId()
+            if var dbContact = try db().fetchContacts(.init(id: [contactId])).first {
+              dbContact.phone = nil
+              try db().saveContact(dbContact)
+            }
+          } catch {
+            subscriber.send(.didFail(error.localizedDescription))
+          }
+          subscriber.send(.set(\.$isUnregisteringPhone, false))
+          subscriber.send(completion: .finished)
+          return AnyCancellable {}
+        }
+        .subscribe(on: bgQueue)
+        .receive(on: mainQueue)
+        .eraseToEffect()
+
+      case .loadFactsTapped:
+        state.isLoadingFacts = true
+        return Effect.run { subscriber in
+          do {
+            let contactId = try messenger.e2e.tryGet().getContact().getId()
+            if var dbContact = try db().fetchContacts(.init(id: [contactId])).first {
+              let facts = try messenger.ud.tryGet().getFacts()
+              dbContact.username = facts.get(.username)?.value
+              dbContact.email = facts.get(.email)?.value
+              dbContact.phone = facts.get(.phone)?.value
+              try db().saveContact(dbContact)
+            }
+          } catch {
+            subscriber.send(.didFail(error.localizedDescription))
+          }
+          subscriber.send(.set(\.$isLoadingFacts, false))
+          subscriber.send(completion: .finished)
+          return AnyCancellable {}
+        }
+        .subscribe(on: bgQueue)
+        .receive(on: mainQueue)
+        .eraseToEffect()
+
+      case .didFail(let failure):
+        state.alert = .error(failure)
+        return .none
+
+      case .alertDismissed:
+        state.alert = nil
+        return .none
+
+      case .binding(_):
+        return .none
+      }
+    }
+  }
+}
diff --git a/Examples/xx-messenger/Sources/MyContactFeature/MyContactFeature.swift b/Examples/xx-messenger/Sources/MyContactFeature/MyContactFeature.swift
deleted file mode 100644
index 434a1aca3c7cdc74b340c54a22558fa67a90a0eb..0000000000000000000000000000000000000000
--- a/Examples/xx-messenger/Sources/MyContactFeature/MyContactFeature.swift
+++ /dev/null
@@ -1,316 +0,0 @@
-import AppCore
-import Combine
-import ComposableArchitecture
-import Foundation
-import XCTestDynamicOverlay
-import XXClient
-import XXMessengerClient
-import XXModels
-
-public struct MyContactState: Equatable {
-  public enum Field: String, Hashable {
-    case email
-    case emailCode
-    case phone
-    case phoneCode
-  }
-
-  public init(
-    contact: XXModels.Contact? = nil,
-    focusedField: Field? = nil,
-    email: String = "",
-    emailConfirmationID: String? = nil,
-    emailConfirmationCode: String = "",
-    isRegisteringEmail: Bool = false,
-    isConfirmingEmail: Bool = false,
-    isUnregisteringEmail: Bool = false,
-    phone: String = "",
-    phoneConfirmationID: String? = nil,
-    phoneConfirmationCode: String = "",
-    isRegisteringPhone: Bool = false,
-    isConfirmingPhone: Bool = false,
-    isUnregisteringPhone: Bool = false,
-    isLoadingFacts: Bool = false,
-    alert: AlertState<MyContactAction>? = nil
-  ) {
-    self.contact = contact
-    self.focusedField = focusedField
-    self.email = email
-    self.emailConfirmationID = emailConfirmationID
-    self.emailConfirmationCode = emailConfirmationCode
-    self.isRegisteringEmail = isRegisteringEmail
-    self.isConfirmingEmail = isConfirmingEmail
-    self.isUnregisteringEmail = isUnregisteringEmail
-    self.phone = phone
-    self.phoneConfirmationID = phoneConfirmationID
-    self.phoneConfirmationCode = phoneConfirmationCode
-    self.isRegisteringPhone = isRegisteringPhone
-    self.isConfirmingPhone = isConfirmingPhone
-    self.isUnregisteringPhone = isUnregisteringPhone
-    self.isLoadingFacts = isLoadingFacts
-    self.alert = alert
-  }
-
-  public var contact: XXModels.Contact?
-  @BindableState public var focusedField: Field?
-  @BindableState public var email: String
-  @BindableState public var emailConfirmationID: String?
-  @BindableState public var emailConfirmationCode: String
-  @BindableState public var isRegisteringEmail: Bool
-  @BindableState public var isConfirmingEmail: Bool
-  @BindableState public var isUnregisteringEmail: Bool
-  @BindableState public var phone: String
-  @BindableState public var phoneConfirmationID: String?
-  @BindableState public var phoneConfirmationCode: String
-  @BindableState public var isRegisteringPhone: Bool
-  @BindableState public var isConfirmingPhone: Bool
-  @BindableState public var isUnregisteringPhone: Bool
-  @BindableState public var isLoadingFacts: Bool
-  public var alert: AlertState<MyContactAction>?
-}
-
-public enum MyContactAction: Equatable, BindableAction {
-  case start
-  case contactFetched(XXModels.Contact?)
-  case registerEmailTapped
-  case confirmEmailTapped
-  case unregisterEmailTapped
-  case registerPhoneTapped
-  case confirmPhoneTapped
-  case unregisterPhoneTapped
-  case loadFactsTapped
-  case didFail(String)
-  case alertDismissed
-  case binding(BindingAction<MyContactState>)
-}
-
-public struct MyContactEnvironment {
-  public init(
-    messenger: Messenger,
-    db: DBManagerGetDB,
-    mainQueue: AnySchedulerOf<DispatchQueue>,
-    bgQueue: AnySchedulerOf<DispatchQueue>
-  ) {
-    self.messenger = messenger
-    self.db = db
-    self.mainQueue = mainQueue
-    self.bgQueue = bgQueue
-  }
-
-  public var messenger: Messenger
-  public var db: DBManagerGetDB
-  public var mainQueue: AnySchedulerOf<DispatchQueue>
-  public var bgQueue: AnySchedulerOf<DispatchQueue>
-}
-
-#if DEBUG
-extension MyContactEnvironment {
-  public static let unimplemented = MyContactEnvironment(
-    messenger: .unimplemented,
-    db: .unimplemented,
-    mainQueue: .unimplemented,
-    bgQueue: .unimplemented
-  )
-}
-#endif
-
-public let myContactReducer = Reducer<MyContactState, MyContactAction, MyContactEnvironment>
-{ state, action, env in
-  enum DBFetchEffectID {}
-
-  switch action {
-  case .start:
-    return Effect
-      .catching { try env.messenger.e2e.tryGet().getContact().getId() }
-      .tryMap { try env.db().fetchContactsPublisher(.init(id: [$0])) }
-      .flatMap { $0 }
-      .assertNoFailure()
-      .map(\.first)
-      .map(MyContactAction.contactFetched)
-      .subscribe(on: env.bgQueue)
-      .receive(on: env.mainQueue)
-      .eraseToEffect()
-      .cancellable(id: DBFetchEffectID.self, cancelInFlight: true)
-
-  case .contactFetched(let contact):
-    state.contact = contact
-    return .none
-
-  case .registerEmailTapped:
-    state.focusedField = nil
-    state.isRegisteringEmail = true
-    return Effect.run { [state] subscriber in
-      do {
-        let ud = try env.messenger.ud.tryGet()
-        let fact = Fact(type: .email, value: state.email)
-        let confirmationID = try ud.sendRegisterFact(fact)
-        subscriber.send(.set(\.$emailConfirmationID, confirmationID))
-      } catch {
-        subscriber.send(.didFail(error.localizedDescription))
-      }
-      subscriber.send(.set(\.$isRegisteringEmail, false))
-      subscriber.send(completion: .finished)
-      return AnyCancellable {}
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-
-  case .confirmEmailTapped:
-    guard let confirmationID = state.emailConfirmationID else { return .none }
-    state.focusedField = nil
-    state.isConfirmingEmail = true
-    return Effect.run { [state] subscriber in
-      do {
-        let ud = try env.messenger.ud.tryGet()
-        try ud.confirmFact(confirmationId: confirmationID, code: state.emailConfirmationCode)
-        let contactId = try env.messenger.e2e.tryGet().getContact().getId()
-        if var dbContact = try env.db().fetchContacts(.init(id: [contactId])).first {
-          dbContact.email = state.email
-          try env.db().saveContact(dbContact)
-        }
-        subscriber.send(.set(\.$email, ""))
-        subscriber.send(.set(\.$emailConfirmationID, nil))
-        subscriber.send(.set(\.$emailConfirmationCode, ""))
-      } catch {
-        subscriber.send(.didFail(error.localizedDescription))
-      }
-      subscriber.send(.set(\.$isConfirmingEmail, false))
-      subscriber.send(completion: .finished)
-      return AnyCancellable {}
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-
-  case .unregisterEmailTapped:
-    guard let email = state.contact?.email else { return .none }
-    state.isUnregisteringEmail = true
-    return Effect.run { [state] subscriber in
-      do {
-        let ud: UserDiscovery = try env.messenger.ud.tryGet()
-        let fact = Fact(type: .email, value: email)
-        try ud.removeFact(fact)
-        let contactId = try env.messenger.e2e.tryGet().getContact().getId()
-        if var dbContact = try env.db().fetchContacts(.init(id: [contactId])).first {
-          dbContact.email = nil
-          try env.db().saveContact(dbContact)
-        }
-      } catch {
-        subscriber.send(.didFail(error.localizedDescription))
-      }
-      subscriber.send(.set(\.$isUnregisteringEmail, false))
-      subscriber.send(completion: .finished)
-      return AnyCancellable {}
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-
-  case .registerPhoneTapped:
-    state.focusedField = nil
-    state.isRegisteringPhone = true
-    return Effect.run { [state] subscriber in
-      do {
-        let ud = try env.messenger.ud.tryGet()
-        let fact = Fact(type: .phone, value: state.phone)
-        let confirmationID = try ud.sendRegisterFact(fact)
-        subscriber.send(.set(\.$phoneConfirmationID, confirmationID))
-      } catch {
-        subscriber.send(.didFail(error.localizedDescription))
-      }
-      subscriber.send(.set(\.$isRegisteringPhone, false))
-      subscriber.send(completion: .finished)
-      return AnyCancellable {}
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-
-  case .confirmPhoneTapped:
-    guard let confirmationID = state.phoneConfirmationID else { return .none }
-    state.focusedField = nil
-    state.isConfirmingPhone = true
-    return Effect.run { [state] subscriber in
-      do {
-        let ud = try env.messenger.ud.tryGet()
-        try ud.confirmFact(confirmationId: confirmationID, code: state.phoneConfirmationCode)
-        let contactId = try env.messenger.e2e.tryGet().getContact().getId()
-        if var dbContact = try env.db().fetchContacts(.init(id: [contactId])).first {
-          dbContact.phone = state.phone
-          try env.db().saveContact(dbContact)
-        }
-        subscriber.send(.set(\.$phone, ""))
-        subscriber.send(.set(\.$phoneConfirmationID, nil))
-        subscriber.send(.set(\.$phoneConfirmationCode, ""))
-      } catch {
-        subscriber.send(.didFail(error.localizedDescription))
-      }
-      subscriber.send(.set(\.$isConfirmingPhone, false))
-      subscriber.send(completion: .finished)
-      return AnyCancellable {}
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-
-  case .unregisterPhoneTapped:
-    guard let phone = state.contact?.phone else { return .none }
-    state.isUnregisteringPhone = true
-    return Effect.run { [state] subscriber in
-      do {
-        let ud: UserDiscovery = try env.messenger.ud.tryGet()
-        let fact = Fact(type: .phone, value: phone)
-        try ud.removeFact(fact)
-        let contactId = try env.messenger.e2e.tryGet().getContact().getId()
-        if var dbContact = try env.db().fetchContacts(.init(id: [contactId])).first {
-          dbContact.phone = nil
-          try env.db().saveContact(dbContact)
-        }
-      } catch {
-        subscriber.send(.didFail(error.localizedDescription))
-      }
-      subscriber.send(.set(\.$isUnregisteringPhone, false))
-      subscriber.send(completion: .finished)
-      return AnyCancellable {}
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-
-  case .loadFactsTapped:
-    state.isLoadingFacts = true
-    return Effect.run { subscriber in
-      do {
-        let contactId = try env.messenger.e2e.tryGet().getContact().getId()
-        if var dbContact = try env.db().fetchContacts(.init(id: [contactId])).first {
-          let facts = try env.messenger.ud.tryGet().getFacts()
-          dbContact.username = facts.get(.username)?.value
-          dbContact.email = facts.get(.email)?.value
-          dbContact.phone = facts.get(.phone)?.value
-          try env.db().saveContact(dbContact)
-        }
-      } catch {
-        subscriber.send(.didFail(error.localizedDescription))
-      }
-      subscriber.send(.set(\.$isLoadingFacts, false))
-      subscriber.send(completion: .finished)
-      return AnyCancellable {}
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-
-  case .didFail(let failure):
-    state.alert = .error(failure)
-    return .none
-
-  case .alertDismissed:
-    state.alert = nil
-    return .none
-
-  case .binding(_):
-    return .none
-  }
-}
-.binding()
diff --git a/Examples/xx-messenger/Sources/MyContactFeature/MyContactView.swift b/Examples/xx-messenger/Sources/MyContactFeature/MyContactView.swift
index d32a6f68848e89ad7eeb4a9bf5f25b543d379f40..b5cd127ed53e7037a278e476147a53ae0b42ebc7 100644
--- a/Examples/xx-messenger/Sources/MyContactFeature/MyContactView.swift
+++ b/Examples/xx-messenger/Sources/MyContactFeature/MyContactView.swift
@@ -4,15 +4,15 @@ import SwiftUI
 import XXModels
 
 public struct MyContactView: View {
-  public init(store: Store<MyContactState, MyContactAction>) {
+  public init(store: StoreOf<MyContactComponent>) {
     self.store = store
   }
 
-  let store: Store<MyContactState, MyContactAction>
-  @FocusState var focusedField: MyContactState.Field?
+  let store: StoreOf<MyContactComponent>
+  @FocusState var focusedField: MyContactComponent.State.Field?
 
   struct ViewState: Equatable {
-    init(state: MyContactState) {
+    init(state: MyContactComponent.State) {
       contact = state.contact
       focusedField = state.focusedField
       email = state.email
@@ -31,7 +31,7 @@ public struct MyContactView: View {
     }
 
     var contact: XXModels.Contact?
-    var focusedField: MyContactState.Field?
+    var focusedField: MyContactComponent.State.Field?
     var email: String
     var emailConfirmation: Bool
     var emailCode: String
@@ -86,7 +86,7 @@ public struct MyContactView: View {
               TextField(
                 text: viewStore.binding(
                   get: \.email,
-                  send: { MyContactAction.set(\.$email, $0) }
+                  send: { MyContactComponent.Action.set(\.$email, $0) }
                 ),
                 prompt: Text("Enter email"),
                 label: { Text("Email") }
@@ -99,7 +99,7 @@ public struct MyContactView: View {
                 TextField(
                   text: viewStore.binding(
                     get: \.emailCode,
-                    send: { MyContactAction.set(\.$emailConfirmationCode, $0) }
+                    send: { MyContactComponent.Action.set(\.$emailConfirmationCode, $0) }
                   ),
                   prompt: Text("Enter confirmation code"),
                   label: { Text("Confirmation code") }
@@ -163,7 +163,7 @@ public struct MyContactView: View {
               TextField(
                 text: viewStore.binding(
                   get: \.phone,
-                  send: { MyContactAction.set(\.$phone, $0) }
+                  send: { MyContactComponent.Action.set(\.$phone, $0) }
                 ),
                 prompt: Text("Enter phone"),
                 label: { Text("Phone") }
@@ -176,7 +176,7 @@ public struct MyContactView: View {
                 TextField(
                   text: viewStore.binding(
                     get: \.phoneCode,
-                    send: { MyContactAction.set(\.$phoneConfirmationCode, $0) }
+                    send: { MyContactComponent.Action.set(\.$phoneConfirmationCode, $0) }
                   ),
                   prompt: Text("Enter confirmation code"),
                   label: { Text("Confirmation code") }
@@ -250,9 +250,8 @@ public struct MyContactView_Previews: PreviewProvider {
   public static var previews: some View {
     NavigationView {
       MyContactView(store: Store(
-        initialState: MyContactState(),
-        reducer: .empty,
-        environment: ()
+        initialState: MyContactComponent.State(),
+        reducer: EmptyReducer()
       ))
     }
   }
diff --git a/Examples/xx-messenger/Tests/MyContactFeatureTests/MyContactFeatureTests.swift b/Examples/xx-messenger/Tests/MyContactFeatureTests/MyContactComponentTests.swift
similarity index 80%
rename from Examples/xx-messenger/Tests/MyContactFeatureTests/MyContactFeatureTests.swift
rename to Examples/xx-messenger/Tests/MyContactFeatureTests/MyContactComponentTests.swift
index 830e97156363b151fbff21276169d8dfc2095720..358db1c2bd3a6633072249d10d6efacf245366f3 100644
--- a/Examples/xx-messenger/Tests/MyContactFeatureTests/MyContactFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/MyContactFeatureTests/MyContactComponentTests.swift
@@ -7,22 +7,21 @@ import XXMessengerClient
 import XXModels
 @testable import MyContactFeature
 
-final class MyContactFeatureTests: XCTestCase {
+final class MyContactComponentTests: XCTestCase {
   func testStart() {
     let contactId = "contact-id".data(using: .utf8)!
 
     let store = TestStore(
-      initialState: MyContactState(),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      initialState: MyContactComponent.State(),
+      reducer: MyContactComponent()
     )
 
     var dbDidFetchContacts: [XXModels.Contact.Query] = []
     let dbContactsPublisher = PassthroughSubject<[XXModels.Contact], Error>()
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.e2e.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.e2e.get = {
       var e2e: E2E = .unimplemented
       e2e.getContact.run = {
         var contact: XXClient.Contact = .unimplemented(Data())
@@ -31,7 +30,7 @@ final class MyContactFeatureTests: XCTestCase {
       }
       return e2e
     }
-    store.environment.db.run = {
+    store.dependencies.app.dbManager.getDB.run = {
       var db: Database = .unimplemented
       db.fetchContactsPublisher.run = { query in
         dbDidFetchContacts.append(query)
@@ -65,14 +64,13 @@ final class MyContactFeatureTests: XCTestCase {
     var didSendRegisterFact: [Fact] = []
 
     let store = TestStore(
-      initialState: MyContactState(),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      initialState: MyContactComponent.State(),
+      reducer: MyContactComponent()
     )
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.ud.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.ud.get = {
       var ud: UserDiscovery = .unimplemented
       ud.sendRegisterFact.run = { fact in
         didSendRegisterFact.append(fact)
@@ -110,14 +108,13 @@ final class MyContactFeatureTests: XCTestCase {
     let failure = Failure()
 
     let store = TestStore(
-      initialState: MyContactState(),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      initialState: MyContactComponent.State(),
+      reducer: MyContactComponent()
     )
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.ud.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.ud.get = {
       var ud: UserDiscovery = .unimplemented
       ud.sendRegisterFact.run = { _ in throw failure }
       return ud
@@ -149,17 +146,16 @@ final class MyContactFeatureTests: XCTestCase {
     var didSaveContact: [XXModels.Contact] = []
 
     let store = TestStore(
-      initialState: MyContactState(
+      initialState: MyContactComponent.State(
         email: email,
         emailConfirmationID: confirmationID
       ),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      reducer: MyContactComponent()
     )
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.ud.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.ud.get = {
       var ud: UserDiscovery = .unimplemented
       ud.confirmFact.run = { id, code in
         didConfirmWithID.append(id)
@@ -167,7 +163,7 @@ final class MyContactFeatureTests: XCTestCase {
       }
       return ud
     }
-    store.environment.messenger.e2e.get = {
+    store.dependencies.app.messenger.e2e.get = {
       var e2e: E2E = .unimplemented
       e2e.getContact.run = {
         var contact: XXClient.Contact = .unimplemented(Data())
@@ -176,7 +172,7 @@ final class MyContactFeatureTests: XCTestCase {
       }
       return e2e
     }
-    store.environment.db.run = {
+    store.dependencies.app.dbManager.getDB.run = {
       var db: Database = .unimplemented
       db.fetchContacts.run = { query in
         didFetchContacts.append(query)
@@ -228,16 +224,15 @@ final class MyContactFeatureTests: XCTestCase {
     let failure = Failure()
 
     let store = TestStore(
-      initialState: MyContactState(
+      initialState: MyContactComponent.State(
         emailConfirmationID: "123"
       ),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      reducer: MyContactComponent()
     )
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.ud.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.ud.get = {
       var ud: UserDiscovery = .unimplemented
       ud.confirmFact.run = { _, _ in throw failure }
       return ud
@@ -266,21 +261,20 @@ final class MyContactFeatureTests: XCTestCase {
     var didSaveContact: [XXModels.Contact] = []
 
     let store = TestStore(
-      initialState: MyContactState(
+      initialState: MyContactComponent.State(
         contact: dbContact
       ),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      reducer: MyContactComponent()
     )
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.ud.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.ud.get = {
       var ud: UserDiscovery = .unimplemented
       ud.removeFact.run = { didRemoveFact.append($0) }
       return ud
     }
-    store.environment.messenger.e2e.get = {
+    store.dependencies.app.messenger.e2e.get = {
       var e2e: E2E = .unimplemented
       e2e.getContact.run = {
         var contact: XXClient.Contact = .unimplemented(Data())
@@ -289,7 +283,7 @@ final class MyContactFeatureTests: XCTestCase {
       }
       return e2e
     }
-    store.environment.db.run = {
+    store.dependencies.app.dbManager.getDB.run = {
       var db: Database = .unimplemented
       db.fetchContacts.run = { query in
         didFetchContacts.append(query)
@@ -322,16 +316,15 @@ final class MyContactFeatureTests: XCTestCase {
     let failure = Failure()
 
     let store = TestStore(
-      initialState: MyContactState(
+      initialState: MyContactComponent.State(
         contact: .init(id: Data(), email: "test@email.com")
       ),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      reducer: MyContactComponent()
     )
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.ud.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.ud.get = {
       var ud: UserDiscovery = .unimplemented
       ud.removeFact.run = { _ in throw failure }
       return ud
@@ -357,14 +350,13 @@ final class MyContactFeatureTests: XCTestCase {
     var didSendRegisterFact: [Fact] = []
 
     let store = TestStore(
-      initialState: MyContactState(),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      initialState: MyContactComponent.State(),
+      reducer: MyContactComponent()
     )
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.ud.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.ud.get = {
       var ud: UserDiscovery = .unimplemented
       ud.sendRegisterFact.run = { fact in
         didSendRegisterFact.append(fact)
@@ -402,14 +394,13 @@ final class MyContactFeatureTests: XCTestCase {
     let failure = Failure()
 
     let store = TestStore(
-      initialState: MyContactState(),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      initialState: MyContactComponent.State(),
+      reducer: MyContactComponent()
     )
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.ud.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.ud.get = {
       var ud: UserDiscovery = .unimplemented
       ud.sendRegisterFact.run = { _ in throw failure }
       return ud
@@ -441,17 +432,16 @@ final class MyContactFeatureTests: XCTestCase {
     var didSaveContact: [XXModels.Contact] = []
 
     let store = TestStore(
-      initialState: MyContactState(
+      initialState: MyContactComponent.State(
         phone: phone,
         phoneConfirmationID: confirmationID
       ),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      reducer: MyContactComponent()
     )
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.ud.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.ud.get = {
       var ud: UserDiscovery = .unimplemented
       ud.confirmFact.run = { id, code in
         didConfirmWithID.append(id)
@@ -459,7 +449,7 @@ final class MyContactFeatureTests: XCTestCase {
       }
       return ud
     }
-    store.environment.messenger.e2e.get = {
+    store.dependencies.app.messenger.e2e.get = {
       var e2e: E2E = .unimplemented
       e2e.getContact.run = {
         var contact: XXClient.Contact = .unimplemented(Data())
@@ -468,7 +458,7 @@ final class MyContactFeatureTests: XCTestCase {
       }
       return e2e
     }
-    store.environment.db.run = {
+    store.dependencies.app.dbManager.getDB.run = {
       var db: Database = .unimplemented
       db.fetchContacts.run = { query in
         didFetchContacts.append(query)
@@ -520,16 +510,15 @@ final class MyContactFeatureTests: XCTestCase {
     let failure = Failure()
 
     let store = TestStore(
-      initialState: MyContactState(
+      initialState: MyContactComponent.State(
         phoneConfirmationID: "123"
       ),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      reducer: MyContactComponent()
     )
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.ud.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.ud.get = {
       var ud: UserDiscovery = .unimplemented
       ud.confirmFact.run = { _, _ in throw failure }
       return ud
@@ -558,21 +547,20 @@ final class MyContactFeatureTests: XCTestCase {
     var didSaveContact: [XXModels.Contact] = []
 
     let store = TestStore(
-      initialState: MyContactState(
+      initialState: MyContactComponent.State(
         contact: dbContact
       ),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      reducer: MyContactComponent()
     )
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.ud.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.ud.get = {
       var ud: UserDiscovery = .unimplemented
       ud.removeFact.run = { didRemoveFact.append($0) }
       return ud
     }
-    store.environment.messenger.e2e.get = {
+    store.dependencies.app.messenger.e2e.get = {
       var e2e: E2E = .unimplemented
       e2e.getContact.run = {
         var contact: XXClient.Contact = .unimplemented(Data())
@@ -581,7 +569,7 @@ final class MyContactFeatureTests: XCTestCase {
       }
       return e2e
     }
-    store.environment.db.run = {
+    store.dependencies.app.dbManager.getDB.run = {
       var db: Database = .unimplemented
       db.fetchContacts.run = { query in
         didFetchContacts.append(query)
@@ -614,16 +602,15 @@ final class MyContactFeatureTests: XCTestCase {
     let failure = Failure()
 
     let store = TestStore(
-      initialState: MyContactState(
+      initialState: MyContactComponent.State(
         contact: .init(id: Data(), phone: "+123456789")
       ),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      reducer: MyContactComponent()
     )
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.ud.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.ud.get = {
       var ud: UserDiscovery = .unimplemented
       ud.removeFact.run = { _ in throw failure }
       return ud
@@ -653,14 +640,13 @@ final class MyContactFeatureTests: XCTestCase {
     var didSaveContact: [XXModels.Contact] = []
 
     let store = TestStore(
-      initialState: MyContactState(),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      initialState: MyContactComponent.State(),
+      reducer: MyContactComponent()
     )
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.e2e.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.e2e.get = {
       var e2e: E2E = .unimplemented
       e2e.getContact.run = {
         var contact: XXClient.Contact = .unimplemented(Data())
@@ -669,7 +655,7 @@ final class MyContactFeatureTests: XCTestCase {
       }
       return e2e
     }
-    store.environment.messenger.ud.get = {
+    store.dependencies.app.messenger.ud.get = {
       var ud: UserDiscovery = .unimplemented
       ud.getFacts.run = {
         [
@@ -680,7 +666,7 @@ final class MyContactFeatureTests: XCTestCase {
       }
       return ud
     }
-    store.environment.db.run = {
+    store.dependencies.app.dbManager.getDB.run = {
       var db: Database = .unimplemented
       db.fetchContacts.run = { query in
         didFetchContacts.append(query)
@@ -714,14 +700,13 @@ final class MyContactFeatureTests: XCTestCase {
     let failure = Failure()
 
     let store = TestStore(
-      initialState: MyContactState(),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      initialState: MyContactComponent.State(),
+      reducer: MyContactComponent()
     )
 
-    store.environment.mainQueue = .immediate
-    store.environment.bgQueue = .immediate
-    store.environment.messenger.e2e.get = {
+    store.dependencies.app.mainQueue = .immediate
+    store.dependencies.app.bgQueue = .immediate
+    store.dependencies.app.messenger.e2e.get = {
       var e2e: E2E = .unimplemented
       e2e.getContact.run = {
         var contact: XXClient.Contact = .unimplemented(Data())
@@ -746,9 +731,8 @@ final class MyContactFeatureTests: XCTestCase {
 
   func testErrorAlert() {
     let store = TestStore(
-      initialState: MyContactState(),
-      reducer: myContactReducer,
-      environment: .unimplemented
+      initialState: MyContactComponent.State(),
+      reducer: MyContactComponent()
     )
 
     let failure = "Something went wrong"