diff --git a/Package.swift b/Package.swift
index 25ebb908a90ad60198cd069fbab071902387730d..45958a19c19a494cb6979c9dac8b55ca1905e56f 100644
--- a/Package.swift
+++ b/Package.swift
@@ -28,6 +28,7 @@ let package = Package(
         .library(name: "PushFeature", targets: ["PushFeature"]),
         .library(name: "SFTPFeature", targets: ["SFTPFeature"]),
         .library(name: "CrashService", targets: ["CrashService"]),
+        .library(name: "TermsFeature", targets: ["TermsFeature"]),
         .library(name: "Presentation", targets: ["Presentation"]),
         .library(name: "ToastFeature", targets: ["ToastFeature"]),
         .library(name: "BackupFeature", targets: ["BackupFeature"]),
@@ -150,6 +151,7 @@ let package = Package(
                 .target(name: "MenuFeature"),
                 .target(name: "PushFeature"),
                 .target(name: "SFTPFeature"),
+                .target(name: "TermsFeature"),
                 .target(name: "ToastFeature"),
                 .target(name: "CrashService"),
                 .target(name: "BackupFeature"),
@@ -507,6 +509,14 @@ let package = Package(
                 .target(name: "DependencyInjection"),
             ]
         ),
+        .target(
+            name: "TermsFeature",
+            dependencies: [
+                .target(name: "Theme"),
+                .target(name: "Shared"),
+                .target(name: "Defaults")
+            ]
+        ),
         .target(
             name: "RequestsFeature",
             dependencies: [
diff --git a/Sources/App/DependencyRegistrator.swift b/Sources/App/DependencyRegistrator.swift
index 05d03f78e33764ef8a3f3cd325b5fa1b9d958c18..e24711457082d4ee7ba1bb51005e73762f656c10 100644
--- a/Sources/App/DependencyRegistrator.swift
+++ b/Sources/App/DependencyRegistrator.swift
@@ -34,6 +34,7 @@ import DependencyInjection
 import ScanFeature
 import ChatFeature
 import MenuFeature
+import TermsFeature
 import BackupFeature
 import SearchFeature
 import LaunchFeature
@@ -111,8 +112,16 @@ struct DependencyRegistrator {
 
         // MARK: Coordinators
 
+        container.register(
+            TermsCoordinator.live(
+                usernameFactory: OnboardingUsernameController.init(_:),
+                chatListFactory: ChatListController.init
+            )
+        )
+
         container.register(
             LaunchCoordinator(
+                termsFactory: TermsConditionsController.init(_:),
                 searchFactory: SearchContainerController.init,
                 requestsFactory: RequestsContainerController.init,
                 chatListFactory: ChatListController.init,
@@ -206,6 +215,7 @@ struct DependencyRegistrator {
                 searchFactory: SearchContainerController.init,
                 welcomeFactory: OnboardingWelcomeController.init,
                 chatListFactory: ChatListController.init,
+                termsFactory: TermsConditionsController.init(_:),
                 usernameFactory: OnboardingUsernameController.init(_:),
                 restoreListFactory: RestoreListController.init(_:),
                 successFactory: OnboardingSuccessController.init(_:),
diff --git a/Sources/Defaults/KeyObject.swift b/Sources/Defaults/KeyObject.swift
index 7757f7ed4fa550c478736b76cd7c1036ef4fde34..0ade4e83639f54a5181b4292936a2d9dee049f60 100644
--- a/Sources/Defaults/KeyObject.swift
+++ b/Sources/Defaults/KeyObject.swift
@@ -21,6 +21,7 @@ public enum Key: String {
     // MARK: General
 
     case theme
+    case acceptedTerms
 
     // MARK: Requests
 
diff --git a/Sources/LaunchFeature/LaunchCoordinator.swift b/Sources/LaunchFeature/LaunchCoordinator.swift
index 28ac7f90d6833c85d43cf5dfc2fd56a0bc4dad23..37035773d6cfd875d5acf6de309b4ac84d72ae6f 100644
--- a/Sources/LaunchFeature/LaunchCoordinator.swift
+++ b/Sources/LaunchFeature/LaunchCoordinator.swift
@@ -5,6 +5,7 @@ import Presentation
 
 public protocol LaunchCoordinating {
     func toChats(from: UIViewController)
+    func toTerms(from: UIViewController)
     func toRequests(from: UIViewController)
     func toSearch(searching: String, from: UIViewController)
     func toOnboarding(with: String, from: UIViewController)
@@ -15,6 +16,7 @@ public protocol LaunchCoordinating {
 public struct LaunchCoordinator: LaunchCoordinating {
     var replacePresenter: Presenting = ReplacePresenter()
 
+    var termsFactory: (String?) -> UIViewController
     var searchFactory: (String) -> UIViewController
     var requestsFactory: () -> UIViewController
     var chatListFactory: () -> UIViewController
@@ -23,6 +25,7 @@ public struct LaunchCoordinator: LaunchCoordinating {
     var groupChatFactory: (GroupInfo) -> UIViewController
 
     public init(
+        termsFactory: @escaping (String?) -> UIViewController,
         searchFactory: @escaping (String) -> UIViewController,
         requestsFactory: @escaping () -> UIViewController,
         chatListFactory: @escaping () -> UIViewController,
@@ -30,6 +33,7 @@ public struct LaunchCoordinator: LaunchCoordinating {
         singleChatFactory: @escaping (Contact) -> UIViewController,
         groupChatFactory: @escaping (GroupInfo) -> UIViewController
     ) {
+        self.termsFactory = termsFactory
         self.searchFactory = searchFactory
         self.requestsFactory = requestsFactory
         self.chatListFactory = chatListFactory
@@ -46,6 +50,11 @@ public extension LaunchCoordinator {
         replacePresenter.present(chatListScreen, screen, from: parent)
     }
 
+    func toTerms(from parent: UIViewController) {
+        let screen = termsFactory(nil)
+        replacePresenter.present(screen, from: parent)
+    }
+
     func toChats(from parent: UIViewController) {
         let screen = chatListFactory()
         replacePresenter.present(screen, from: parent)
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift b/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
index d95169bbd9c5ce078687a77c96768d91e9d2336d..7ef1bae86c8297f1b674f486e93955587afe284b 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
@@ -52,7 +52,7 @@ public final class OnboardingStartController: UIViewController {
         super.viewDidLoad()
 
         screenView.startButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in coordinator.toUsername(with: ndf, from: self) }
+            .sink { [unowned self] in coordinator.toTerms(ndf: ndf, from: self) }
             .store(in: &cancellables)
     }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift b/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
index 3bc4493ebd99899a4b9ea646964816ff0140009e..b1d3feb5cf5047be6cab2948051f4392973c85cc 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
@@ -36,6 +36,7 @@ public final class OnboardingUsernameController: UIViewController {
 
     public override func viewDidLoad() {
         super.viewDidLoad()
+        setupNavigationBar()
         setupScrollView()
         setupBindings()
 
@@ -48,6 +49,26 @@ public final class OnboardingUsernameController: UIViewController {
         }
     }
 
+    private func setupNavigationBar() {
+        navigationItem.backButtonTitle = ""
+
+        let backButton = UIButton()
+        backButton.setImage(Asset.navigationBarBack.image, for: .normal)
+        backButton.tintColor = Asset.neutralActive.color
+        backButton.imageView?.contentMode = .center
+        backButton.snp.makeConstraints { $0.width.equalTo(50) }
+        backButton
+            .publisher(for: .touchUpInside)
+            .receive(on: DispatchQueue.main)
+            .sink { [unowned self] in
+                navigationController?.popViewController(animated: true)
+            }.store(in: &cancellables)
+
+        navigationItem.leftBarButtonItem = UIBarButtonItem(
+            customView: UIStackView(arrangedSubviews: [backButton])
+        )
+    }
+
     private func setupScrollView() {
         scrollViewController.scrollView.backgroundColor = .white
 
diff --git a/Sources/OnboardingFeature/Coordinator/OnboardingCoordinator.swift b/Sources/OnboardingFeature/Coordinator/OnboardingCoordinator.swift
index 59bf66c4e95c27f4a151472e473f657c88c13e1e..9ea57da2c51a02679f40c9132b88498fb139fa68 100644
--- a/Sources/OnboardingFeature/Coordinator/OnboardingCoordinator.swift
+++ b/Sources/OnboardingFeature/Coordinator/OnboardingCoordinator.swift
@@ -11,6 +11,7 @@ public protocol OnboardingCoordinating {
     func toEmail(from: UIViewController)
     func toPhone(from: UIViewController)
     func toWelcome(from: UIViewController)
+    func toTerms(ndf: String, from: UIViewController)
     func toUsername(with: String, from: UIViewController)
     func toRestoreList(with: String, from: UIViewController)
     func toDrawer(_: UIViewController, from: UIViewController)
@@ -46,6 +47,7 @@ public struct OnboardingCoordinator: OnboardingCoordinating {
     var chatListFactory: () -> UIViewController
     var usernameFactory: (String) -> UIViewController
     var restoreListFactory: (String) -> UIViewController
+    var termsFactory: (String?) -> UIViewController
     var successFactory: (OnboardingSuccessModel) -> UIViewController
     var countriesFactory: (@escaping (Country) -> Void) -> UIViewController
     var phoneConfirmationFactory: (AttributeConfirmation, @escaping AttributeControllerClosure) -> UIViewController
@@ -57,6 +59,7 @@ public struct OnboardingCoordinator: OnboardingCoordinating {
         searchFactory: @escaping (String?) -> UIViewController,
         welcomeFactory: @escaping () -> UIViewController,
         chatListFactory: @escaping () -> UIViewController,
+        termsFactory: @escaping (String?) -> UIViewController,
         usernameFactory: @escaping (String) -> UIViewController,
         restoreListFactory: @escaping (String) -> UIViewController,
         successFactory: @escaping (OnboardingSuccessModel) -> UIViewController,
@@ -65,6 +68,7 @@ public struct OnboardingCoordinator: OnboardingCoordinating {
         emailConfirmationFactory: @escaping (AttributeConfirmation, @escaping AttributeControllerClosure) -> UIViewController
     ) {
         self.emailFactory = emailFactory
+        self.termsFactory = termsFactory
         self.phoneFactory = phoneFactory
         self.searchFactory = searchFactory
         self.welcomeFactory = welcomeFactory
@@ -79,6 +83,14 @@ public struct OnboardingCoordinator: OnboardingCoordinating {
 }
 
 public extension OnboardingCoordinator {
+    func toTerms(
+        ndf: String,
+        from parent: UIViewController
+    ) {
+        let screen = termsFactory(ndf)
+        pushPresenter.present(screen, from: parent)
+    }
+
     func toEmail(from parent: UIViewController) {
         let screen = emailFactory()
         replacePresenter.present(screen, from: parent)
diff --git a/Sources/Shared/AutoGenerated/Strings.swift b/Sources/Shared/AutoGenerated/Strings.swift
index 1f65eac1dc1fc32bef4a548cfee612b192f07f3f..03ada00df323371aae8d22c05b50903f9da768d6 100644
--- a/Sources/Shared/AutoGenerated/Strings.swift
+++ b/Sources/Shared/AutoGenerated/Strings.swift
@@ -1224,6 +1224,17 @@ public enum Localized {
     }
   }
 
+  public enum Terms {
+    /// Accept and proceed
+    public static let accept = Localized.tr("Localizable", "terms.accept")
+    /// By enabling the checkbox on the left, you agree with the terms and conditions.
+    public static let radio = Localized.tr("Localizable", "terms.radio")
+    /// Show terms and conditions
+    public static let show = Localized.tr("Localizable", "terms.show")
+    /// Terms #&# Conditions
+    public static let title = Localized.tr("Localizable", "terms.title")
+  }
+
   public enum Ud {
     /// There are no users with that %@.
     public static func noneFound(_ p1: Any) -> String {
diff --git a/Sources/Shared/Resources/en.lproj/Localizable.strings b/Sources/Shared/Resources/en.lproj/Localizable.strings
index 4172e91f1c19da1b3d304f289c43c7dd7cd55e63..033e7a6f2ff8bd973d4eaf2cec0755295c8936b5 100644
--- a/Sources/Shared/Resources/en.lproj/Localizable.strings
+++ b/Sources/Shared/Resources/en.lproj/Localizable.strings
@@ -646,6 +646,17 @@
 "backup.SFTP"
 = "SFTP";
 
+// Terms & Conditions
+
+"terms.title"
+= "Terms #&# Conditions";
+"terms.radio"
+= "By enabling the checkbox on the left, you agree with the terms and conditions.";
+"terms.accept"
+= "Accept and proceed";
+"terms.show"
+= "Show terms and conditions";
+
 // Settings - Delete Account
 
 "settings.delete.title"
diff --git a/Sources/TermsFeature/RadioButton.swift b/Sources/TermsFeature/RadioButton.swift
new file mode 100644
index 0000000000000000000000000000000000000000..43b873ac9939ac8297e466ef4494cf9c78d9512a
--- /dev/null
+++ b/Sources/TermsFeature/RadioButton.swift
@@ -0,0 +1,53 @@
+import UIKit
+import Shared
+
+final class RadioButton: UIControl {
+    private let filledView = UIView()
+    private let containerView = UIView()
+
+    init() {
+        super.init(frame: .zero)
+
+        containerView.layer.borderWidth = 1
+        containerView.layer.cornerRadius = 15
+        containerView.layer.masksToBounds = true
+        containerView.layer.borderColor = UIColor.gray.cgColor
+
+        filledView.isHidden = true
+        filledView.layer.cornerRadius = 10
+        filledView.layer.masksToBounds = true
+        filledView.backgroundColor = Asset.brandPrimary.color
+
+        containerView.isUserInteractionEnabled = false
+        filledView.isUserInteractionEnabled = false
+
+        addSubview(containerView)
+        containerView.addSubview(filledView)
+
+        setupConstraints()
+    }
+
+    required init?(coder: NSCoder) { nil }
+
+    func set(enabled: Bool) {
+        filledView.isHidden = !enabled
+    }
+
+    private func setupConstraints() {
+        containerView.snp.makeConstraints {
+            $0.width.equalTo(30)
+            $0.height.equalTo(30)
+            $0.top.equalToSuperview().offset(5)
+            $0.left.equalToSuperview().offset(5)
+            $0.right.equalToSuperview().offset(-5)
+            $0.bottom.equalToSuperview().offset(-5)
+        }
+
+        filledView.snp.makeConstraints {
+            $0.top.equalToSuperview().offset(5)
+            $0.left.equalToSuperview().offset(5)
+            $0.right.equalToSuperview().offset(-5)
+            $0.bottom.equalToSuperview().offset(-5)
+        }
+    }
+}
diff --git a/Sources/TermsFeature/RadioTextComponent.swift b/Sources/TermsFeature/RadioTextComponent.swift
new file mode 100644
index 0000000000000000000000000000000000000000..64c7b1cfb3d80ccc85284f7544e286666faeb639
--- /dev/null
+++ b/Sources/TermsFeature/RadioTextComponent.swift
@@ -0,0 +1,40 @@
+import UIKit
+import Shared
+
+final class RadioTextComponent: UIView {
+    let titleLabel = UILabel()
+    let radioButton = RadioButton()
+
+    var isEnabled: Bool = false {
+        didSet { radioButton.set(enabled: isEnabled) }
+    }
+
+    init() {
+        super.init(frame: .zero)
+
+        titleLabel.numberOfLines = 0
+        titleLabel.textColor = Asset.neutralBody.color
+        titleLabel.font = Fonts.Mulish.regular.font(size: 13.0)
+
+        addSubview(titleLabel)
+        addSubview(radioButton)
+
+        setupConstraints()
+    }
+
+    required init?(coder: NSCoder) { nil }
+
+    private func setupConstraints() {
+        titleLabel.snp.makeConstraints {
+            $0.left.equalTo(radioButton.snp.right).offset(7)
+            $0.centerY.equalTo(radioButton)
+            $0.right.equalToSuperview()
+        }
+
+        radioButton.snp.makeConstraints {
+            $0.left.equalToSuperview()
+            $0.top.greaterThanOrEqualToSuperview()
+            $0.bottom.equalToSuperview()
+        }
+    }
+}
diff --git a/Sources/TermsFeature/TermsConditionsController.swift b/Sources/TermsFeature/TermsConditionsController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..ea017dd0f01aa1b6a86be0a02f15677d061a9ed1
--- /dev/null
+++ b/Sources/TermsFeature/TermsConditionsController.swift
@@ -0,0 +1,85 @@
+import UIKit
+import Theme
+import Shared
+import Combine
+import Defaults
+import DependencyInjection
+
+public final class TermsConditionsController: UIViewController {
+    @Dependency var coordinator: TermsCoordinator
+    @Dependency var statusBarController: StatusBarStyleControlling
+
+    @KeyObject(.acceptedTerms, defaultValue: false) var didAcceptTerms: Bool
+
+    lazy private var screenView = TermsConditionsView()
+
+    private let ndf: String?
+    private var cancellables = Set<AnyCancellable>()
+
+    public init(_ ndf: String?) {
+        self.ndf = ndf
+        super.init(nibName: nil, bundle: nil)
+    }
+
+    required init?(coder: NSCoder) { nil }
+
+    public override func loadView() {
+        view = screenView
+    }
+
+    public override func viewWillAppear(_ animated: Bool) {
+        super.viewWillAppear(animated)
+        statusBarController.style.send(.darkContent)
+        navigationController?.navigationBar.customize(translucent: true)
+    }
+
+    public override func viewDidLoad() {
+        super.viewDidLoad()
+
+        navigationItem.backButtonTitle = ""
+
+        let backButton = UIButton()
+        backButton.setImage(Asset.navigationBarBack.image, for: .normal)
+        backButton.tintColor = Asset.neutralActive.color
+        backButton.imageView?.contentMode = .center
+        backButton.snp.makeConstraints { $0.width.equalTo(50) }
+        backButton
+            .publisher(for: .touchUpInside)
+            .receive(on: DispatchQueue.main)
+            .sink { [unowned self] in
+                navigationController?.popViewController(animated: true)
+            }.store(in: &cancellables)
+
+        navigationItem.leftBarButtonItem = UIBarButtonItem(
+            customView: UIStackView(arrangedSubviews: [backButton])
+        )
+
+        screenView.radioComponent
+            .radioButton.publisher(for: .touchUpInside)
+            .receive(on: DispatchQueue.main)
+            .sink { [unowned self] in
+                screenView.radioComponent.isEnabled.toggle()
+                screenView.nextButton.isEnabled = screenView.radioComponent.isEnabled
+            }.store(in: &cancellables)
+
+        screenView.nextButton
+            .publisher(for: .touchUpInside)
+            .receive(on: DispatchQueue.main)
+            .sink { [unowned self] in
+                didAcceptTerms = true
+
+                if let ndf = ndf {
+                    coordinator.presentUsername(ndf, self)
+                } else {
+                    coordinator.presentChatList(self)
+                }
+            }.store(in: &cancellables)
+
+        screenView.showTermsButton
+            .publisher(for: .touchUpInside)
+            .receive(on: DispatchQueue.main)
+            .sink { _ in
+                // TODO
+            }.store(in: &cancellables)
+    }
+}
diff --git a/Sources/TermsFeature/TermsConditionsView.swift b/Sources/TermsFeature/TermsConditionsView.swift
new file mode 100644
index 0000000000000000000000000000000000000000..fb7d1198f586cd12ecc3e1b0e1479c5cfba84a41
--- /dev/null
+++ b/Sources/TermsFeature/TermsConditionsView.swift
@@ -0,0 +1,72 @@
+import UIKit
+import Shared
+
+final class TermsConditionsView: UIView {
+    let titleLabel = UILabel()
+    let nextButton = CapsuleButton()
+    let showTermsButton = CapsuleButton()
+    let radioComponent = RadioTextComponent()
+
+    init() {
+        super.init(frame: .zero)
+        backgroundColor = Asset.neutralWhite.color
+
+        let attString = NSMutableAttributedString(string: Localized.Terms.title)
+        let paragraph = NSMutableParagraphStyle()
+        paragraph.alignment = .left
+        paragraph.lineHeightMultiple = 1.15
+
+        attString.addAttribute(.paragraphStyle, value: paragraph)
+        attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
+        attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
+
+        attString.addAttributes(attributes: [
+            .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
+            .foregroundColor: Asset.brandPrimary.color
+        ], betweenCharacters: "#")
+
+        titleLabel.numberOfLines = 0
+        titleLabel.attributedText = attString
+
+        radioComponent.titleLabel.text = Localized.Terms.radio
+
+        nextButton.isEnabled = false
+        nextButton.set(style: .brandColored, title: Localized.Terms.accept)
+        showTermsButton.set(style: .seeThrough, title: Localized.Terms.show)
+
+        addSubview(titleLabel)
+        addSubview(nextButton)
+        addSubview(radioComponent)
+        addSubview(showTermsButton)
+
+        setupConstraints()
+    }
+
+    required init?(coder: NSCoder) { nil }
+
+    private func setupConstraints() {
+        titleLabel.snp.makeConstraints {
+            $0.top.equalTo(safeAreaLayoutGuide).offset(30)
+            $0.left.equalToSuperview().offset(38)
+            $0.right.equalToSuperview().offset(-44)
+        }
+
+        radioComponent.snp.makeConstraints {
+            $0.left.equalToSuperview().offset(40)
+            $0.right.equalToSuperview().offset(-40)
+            $0.bottom.equalTo(nextButton.snp.top).offset(-20)
+        }
+
+        nextButton.snp.makeConstraints {
+            $0.left.equalToSuperview().offset(40)
+            $0.right.equalToSuperview().offset(-40)
+            $0.bottom.equalTo(showTermsButton.snp.top).offset(-10)
+        }
+
+        showTermsButton.snp.makeConstraints {
+            $0.left.equalToSuperview().offset(40)
+            $0.right.equalToSuperview().offset(-40)
+            $0.bottom.equalTo(safeAreaLayoutGuide).offset(-40)
+        }
+    }
+}
diff --git a/Sources/TermsFeature/TermsCoordinator.swift b/Sources/TermsFeature/TermsCoordinator.swift
new file mode 100644
index 0000000000000000000000000000000000000000..daff90e4b1b81b18e75e3a6e34557a3478e26f57
--- /dev/null
+++ b/Sources/TermsFeature/TermsCoordinator.swift
@@ -0,0 +1,25 @@
+import UIKit
+import Presentation
+
+public struct TermsCoordinator {
+    var presentChatList: (UIViewController) -> Void
+    var presentUsername: (String, UIViewController) -> Void
+}
+
+public extension TermsCoordinator {
+    static func live(
+        usernameFactory: @escaping (String) -> UIViewController,
+        chatListFactory: @escaping () -> UIViewController
+    ) -> Self {
+        .init(
+            presentChatList: { parent in
+                let presenter = ReplacePresenter()
+                presenter.present(chatListFactory(), from: parent)
+            },
+            presentUsername: { ndf, parent in
+                let presenter = PushPresenter()
+                presenter.present(usernameFactory(ndf), from: parent)
+            }
+        )
+    }
+}