diff --git a/android/app/build.gradle b/android/app/build.gradle
index 5d2c429a6b75..0f6ed20eb937 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -161,11 +161,11 @@ android {
     }
     signingConfigs {
         release {
-            if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
-                storeFile file(MYAPP_UPLOAD_STORE_FILE)
-                storePassword MYAPP_UPLOAD_STORE_PASSWORD
-                keyAlias MYAPP_UPLOAD_KEY_ALIAS
-                keyPassword MYAPP_UPLOAD_KEY_PASSWORD
+            if (project.hasProperty('RORY_TEST_KEYSTORE_FILE')) {
+                storeFile file(RORY_TEST_KEYSTORE_FILE)
+                storePassword RORY_TEST_STORE_PASSWORD
+                keyAlias RORY_TEST_KEY_ALIAS
+                keyPassword RORY_TEST_KEY_PASSWORD
             }
         }
         debug {
@@ -200,6 +200,10 @@ android {
 
         }
     }
+
+    lintOptions {
+        checkReleaseBuilds false
+    }
 }
 
 dependencies {
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 95162a30af5a..0b51d3987505 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -22,7 +22,8 @@
       android:icon="@mipmap/ic_launcher"
       android:roundIcon="@mipmap/ic_launcher_round"
       android:allowBackup="false"
-      android:theme="@style/AppTheme">
+      android:theme="@style/AppTheme"
+      android:debuggable="true">
       <activity
         android:name=".MainActivity"
         android:label="@string/app_name"
diff --git a/android/app/src/main/assets/airshipconfig.properties b/android/app/src/main/assets/airshipconfig.properties
index 6e37dfb7465e..9562d8f158b9 100644
--- a/android/app/src/main/assets/airshipconfig.properties
+++ b/android/app/src/main/assets/airshipconfig.properties
@@ -1,8 +1,10 @@
 developmentAppKey = uulSSfTDQJ2r0PMpjRrhmQ
 developmentAppSecret = D4Bhf0HrQEehrPua74Tyiw
 
-productionAppKey = 55vypj0ARc6cN09MX7ogtQ
-productionAppSecret = EsSaqbdLSvmyC6kSBFJCtQ
+productionAppKey = uulSSfTDQJ2r0PMpjRrhmQ
+productionAppSecret = D4Bhf0HrQEehrPua74Tyiw
+
+logLevel = verbose
 
 # Notification Customization
 notificationIcon = ic_notification
diff --git a/ios/ExpensifyCash.xcodeproj/project.pbxproj b/ios/ExpensifyCash.xcodeproj/project.pbxproj
index 3f740ca957f2..48975cbfc9ed 100644
--- a/ios/ExpensifyCash.xcodeproj/project.pbxproj
+++ b/ios/ExpensifyCash.xcodeproj/project.pbxproj
@@ -25,13 +25,13 @@
 		52477A09739546F4814EA25F /* GTAmericaExpMono-Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = 0DE5D096095C41EE96746C9E /* GTAmericaExpMono-Bd.otf */; };
 		6856B78873B64C44A92E51DB /* GTAmericaExp-MdIt.otf in Resources */ = {isa = PBXBuildFile; fileRef = DB5A1365442D4419AF6F08E5 /* GTAmericaExp-MdIt.otf */; };
 		70CF6E82262E297300711ADC /* BootSplash.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 70CF6E81262E297300711ADC /* BootSplash.storyboard */; };
+		76619227EA8BB9DF4BF36236 /* libPods-ExpensifyCash-ExpensifyCashTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C75B9D1040A9A06FB09B46EE /* libPods-ExpensifyCash-ExpensifyCashTests.a */; };
 		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 		8821A238A081483FA947BC4E /* GTAmericaExp-RgIt.otf in Resources */ = {isa = PBXBuildFile; fileRef = 918D7FEFF96242E6B5F5E14D /* GTAmericaExp-RgIt.otf */; };
-		A3436007AC25B52D4421EDFE /* libPods-ExpensifyCash-ExpensifyCashTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D9772847002A7309594CFB3C /* libPods-ExpensifyCash-ExpensifyCashTests.a */; };
-		DA1351CF1BC4929C869D7874 /* libPods-ExpensifyCash.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19505195D8D4A1D33ACBECCF /* libPods-ExpensifyCash.a */; };
 		DB77016704074197AB6633BB /* GTAmericaExpMono-RgIt.otf in Resources */ = {isa = PBXBuildFile; fileRef = 5150E5D0D7F74DBA8D7C1914 /* GTAmericaExpMono-RgIt.otf */; };
 		E9DF872D2525201700607FDC /* AirshipConfig.plist in Resources */ = {isa = PBXBuildFile; fileRef = E9DF872C2525201700607FDC /* AirshipConfig.plist */; };
 		ED814D34526B415CAFA0451E /* GTAmericaExpMono-BdIt.otf in Resources */ = {isa = PBXBuildFile; fileRef = 3981452A2C7340EBBA2B9BD1 /* GTAmericaExpMono-BdIt.otf */; };
+		F6BDE056DEB0C6A30855CD7E /* libPods-ExpensifyCash.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C91F3560D48B5F2692B55D /* libPods-ExpensifyCash.a */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -60,24 +60,24 @@
 		13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ExpensifyCash/Info.plist; sourceTree = "<group>"; };
 		13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ExpensifyCash/main.m; sourceTree = "<group>"; };
 		18D050DF262400AF000D658B /* BridgingFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BridgingFile.swift; sourceTree = "<group>"; };
-		19505195D8D4A1D33ACBECCF /* libPods-ExpensifyCash.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ExpensifyCash.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 		3981452A2C7340EBBA2B9BD1 /* GTAmericaExpMono-BdIt.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExpMono-BdIt.otf"; path = "../assets/fonts/GTAmericaExpMono-BdIt.otf"; sourceTree = "<group>"; };
-		40EE174FE0E5010DA25F3180 /* Pods-ExpensifyCash.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpensifyCash.debug.xcconfig"; path = "Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash.debug.xcconfig"; sourceTree = "<group>"; };
+		42C91F3560D48B5F2692B55D /* libPods-ExpensifyCash.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ExpensifyCash.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		51191C9E80935A80099F67B4 /* Pods-ExpensifyCash.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpensifyCash.release.xcconfig"; path = "Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash.release.xcconfig"; sourceTree = "<group>"; };
 		5150E5D0D7F74DBA8D7C1914 /* GTAmericaExpMono-RgIt.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExpMono-RgIt.otf"; path = "../assets/fonts/GTAmericaExpMono-RgIt.otf"; sourceTree = "<group>"; };
-		5E0275D64694B453A3EE297D /* Pods-ExpensifyCash.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpensifyCash.release.xcconfig"; path = "Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash.release.xcconfig"; sourceTree = "<group>"; };
 		67D5C3A6A7FA417C8A853FC1 /* GTAmericaExp-Light.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-Light.otf"; path = "../assets/fonts/GTAmericaExp-Light.otf"; sourceTree = "<group>"; };
+		6F9F2F6F4E0F0090A238B760 /* Pods-ExpensifyCash.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpensifyCash.debug.xcconfig"; path = "Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash.debug.xcconfig"; sourceTree = "<group>"; };
 		70CF6E81262E297300711ADC /* BootSplash.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = BootSplash.storyboard; path = ExpensifyCash/BootSplash.storyboard; sourceTree = "<group>"; };
 		81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = ExpensifyCash/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		8437A5A38F2047E0BCCD7C2F /* GTAmericaExpMono-Rg.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExpMono-Rg.otf"; path = "../assets/fonts/GTAmericaExpMono-Rg.otf"; sourceTree = "<group>"; };
+		8505C557B697659B3983EF08 /* Pods-ExpensifyCash-ExpensifyCashTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpensifyCash-ExpensifyCashTests.debug.xcconfig"; path = "Target Support Files/Pods-ExpensifyCash-ExpensifyCashTests/Pods-ExpensifyCash-ExpensifyCashTests.debug.xcconfig"; sourceTree = "<group>"; };
 		8C7003903C1E4957824899BB /* GTAmericaExp-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-Regular.otf"; path = "../assets/fonts/GTAmericaExp-Regular.otf"; sourceTree = "<group>"; };
 		918D7FEFF96242E6B5F5E14D /* GTAmericaExp-RgIt.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-RgIt.otf"; path = "../assets/fonts/GTAmericaExp-RgIt.otf"; sourceTree = "<group>"; };
 		A292718541C841859D97DF2F /* GTAmericaExp-Thin.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-Thin.otf"; path = "../assets/fonts/GTAmericaExp-Thin.otf"; sourceTree = "<group>"; };
 		A5AAD008CBD84A6CAEB9AC97 /* GTAmericaExp-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-Bold.otf"; path = "../assets/fonts/GTAmericaExp-Bold.otf"; sourceTree = "<group>"; };
 		A8D6F2F722FD4E66A38EBBB6 /* GTAmericaExp-BdIt.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-BdIt.otf"; path = "../assets/fonts/GTAmericaExp-BdIt.otf"; sourceTree = "<group>"; };
+		A9454D0E01D17128C0732883 /* Pods-ExpensifyCash-ExpensifyCashTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpensifyCash-ExpensifyCashTests.release.xcconfig"; path = "Target Support Files/Pods-ExpensifyCash-ExpensifyCashTests/Pods-ExpensifyCash-ExpensifyCashTests.release.xcconfig"; sourceTree = "<group>"; };
 		AE65058949E14DA5A2D5435D /* GTAmericaExp-Medium.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-Medium.otf"; path = "../assets/fonts/GTAmericaExp-Medium.otf"; sourceTree = "<group>"; };
-		B82386231652D749850CFC70 /* Pods-ExpensifyCash-ExpensifyCashTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpensifyCash-ExpensifyCashTests.debug.xcconfig"; path = "Target Support Files/Pods-ExpensifyCash-ExpensifyCashTests/Pods-ExpensifyCash-ExpensifyCashTests.debug.xcconfig"; sourceTree = "<group>"; };
-		D111222CBD2088E51A5BB624 /* Pods-ExpensifyCash-ExpensifyCashTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpensifyCash-ExpensifyCashTests.release.xcconfig"; path = "Target Support Files/Pods-ExpensifyCash-ExpensifyCashTests/Pods-ExpensifyCash-ExpensifyCashTests.release.xcconfig"; sourceTree = "<group>"; };
-		D9772847002A7309594CFB3C /* libPods-ExpensifyCash-ExpensifyCashTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ExpensifyCash-ExpensifyCashTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		C75B9D1040A9A06FB09B46EE /* libPods-ExpensifyCash-ExpensifyCashTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ExpensifyCash-ExpensifyCashTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 		DB5A1365442D4419AF6F08E5 /* GTAmericaExp-MdIt.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-MdIt.otf"; path = "../assets/fonts/GTAmericaExp-MdIt.otf"; sourceTree = "<group>"; };
 		E9DF872C2525201700607FDC /* AirshipConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = AirshipConfig.plist; sourceTree = "<group>"; };
 		ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
@@ -89,7 +89,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				A3436007AC25B52D4421EDFE /* libPods-ExpensifyCash-ExpensifyCashTests.a in Frameworks */,
+				76619227EA8BB9DF4BF36236 /* libPods-ExpensifyCash-ExpensifyCashTests.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -97,7 +97,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				DA1351CF1BC4929C869D7874 /* libPods-ExpensifyCash.a in Frameworks */,
+				F6BDE056DEB0C6A30855CD7E /* libPods-ExpensifyCash.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -145,8 +145,8 @@
 			children = (
 				ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
 				ED2971642150620600B7C4FE /* JavaScriptCore.framework */,
-				19505195D8D4A1D33ACBECCF /* libPods-ExpensifyCash.a */,
-				D9772847002A7309594CFB3C /* libPods-ExpensifyCash-ExpensifyCashTests.a */,
+				42C91F3560D48B5F2692B55D /* libPods-ExpensifyCash.a */,
+				C75B9D1040A9A06FB09B46EE /* libPods-ExpensifyCash-ExpensifyCashTests.a */,
 			);
 			name = Frameworks;
 			sourceTree = "<group>";
@@ -206,10 +206,10 @@
 		EC29677F0A49C2946A495A33 /* Pods */ = {
 			isa = PBXGroup;
 			children = (
-				40EE174FE0E5010DA25F3180 /* Pods-ExpensifyCash.debug.xcconfig */,
-				5E0275D64694B453A3EE297D /* Pods-ExpensifyCash.release.xcconfig */,
-				B82386231652D749850CFC70 /* Pods-ExpensifyCash-ExpensifyCashTests.debug.xcconfig */,
-				D111222CBD2088E51A5BB624 /* Pods-ExpensifyCash-ExpensifyCashTests.release.xcconfig */,
+				6F9F2F6F4E0F0090A238B760 /* Pods-ExpensifyCash.debug.xcconfig */,
+				51191C9E80935A80099F67B4 /* Pods-ExpensifyCash.release.xcconfig */,
+				8505C557B697659B3983EF08 /* Pods-ExpensifyCash-ExpensifyCashTests.debug.xcconfig */,
+				A9454D0E01D17128C0732883 /* Pods-ExpensifyCash-ExpensifyCashTests.release.xcconfig */,
 			);
 			path = Pods;
 			sourceTree = "<group>";
@@ -221,12 +221,12 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "ExpensifyCashTests" */;
 			buildPhases = (
-				538F0530BD355DE69016FC8D /* [CP] Check Pods Manifest.lock */,
+				8DFA5A00696B687F79C95016 /* [CP] Check Pods Manifest.lock */,
 				00E356EA1AD99517003FC87E /* Sources */,
 				00E356EB1AD99517003FC87E /* Frameworks */,
 				00E356EC1AD99517003FC87E /* Resources */,
-				DC5669E1DEB80DD839FDB293 /* [CP] Embed Pods Frameworks */,
-				D91BC49ED9E5B6C37CAABCC6 /* [CP] Copy Pods Resources */,
+				508FBBA985FA02D6C17543EF /* [CP] Embed Pods Frameworks */,
+				2B952465AAB48F24B1242706 /* [CP] Copy Pods Resources */,
 			);
 			buildRules = (
 			);
@@ -242,16 +242,16 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ExpensifyCash" */;
 			buildPhases = (
-				BD50DAA2FC45BE14BFB945D0 /* [CP] Check Pods Manifest.lock */,
+				9ADAD62C841619370715F04D /* [CP] Check Pods Manifest.lock */,
 				FD10A7F022414F080027D42C /* Start Packager */,
 				13B07F871A680F5B00A75B9A /* Sources */,
 				13B07F8C1A680F5B00A75B9A /* Frameworks */,
 				13B07F8E1A680F5B00A75B9A /* Resources */,
 				00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
-				8575AEF2E98CE400DE51E589 /* [CP] Embed Pods Frameworks */,
-				1FE23122F2FCC35F85E0E2F7 /* [CP] Copy Pods Resources */,
-				CF6C6C97851DBF01CDAE664E /* [CP-User] [RNFB] Core Configuration */,
-				5717025076C7AEA43883A0AC /* [CP-User] [RNFB] Crashlytics Configuration */,
+				2B16A01E32805491D3D0C2C7 /* [CP] Embed Pods Frameworks */,
+				2FF33D22F22E13C0294AF784 /* [CP] Copy Pods Resources */,
+				98C853189A534B46B0295A00 /* [CP-User] [RNFB] Core Configuration */,
+				E0A3A156B5B4C0811DDF7822 /* [CP-User] [RNFB] Crashlytics Configuration */,
 			);
 			buildRules = (
 			);
@@ -278,7 +278,7 @@
 					13B07F861A680F5B00A75B9A = {
 						DevelopmentTeam = 368M544MTT;
 						LastSwiftMigration = 1230;
-						ProvisioningStyle = Manual;
+						ProvisioningStyle = Automatic;
 					};
 				};
 			};
@@ -350,13 +350,35 @@
 			shellPath = /bin/sh;
 			shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh";
 		};
-		1FE23122F2FCC35F85E0E2F7 /* [CP] Copy Pods Resources */ = {
+		2B16A01E32805491D3D0C2C7 /* [CP] Embed Pods Frameworks */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash-resources.sh",
+				"${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash-frameworks.sh",
+				"${PODS_XCFRAMEWORKS_BUILD_DIR}/Onfido/Onfido.framework/Onfido",
+				"${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL/OpenSSL.framework/OpenSSL",
+				"${PODS_XCFRAMEWORKS_BUILD_DIR}/LinkKit/LinkKit.framework/LinkKit",
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputPaths = (
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Onfido.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LinkKit.framework",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+		2B952465AAB48F24B1242706 /* [CP] Copy Pods Resources */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash-ExpensifyCashTests/Pods-ExpensifyCash-ExpensifyCashTests-resources.sh",
 				"${PODS_ROOT}/Airship/Airship/AirshipAutomation/Resources/UAAutomationActions.plist",
 				"${PODS_ROOT}/Airship/Airship/AirshipAutomation/Resources/UAInAppMessageBannerContentView.xib",
 				"${PODS_ROOT}/Airship/Airship/AirshipAutomation/Resources/UAInAppMessageBannerView.xib",
@@ -475,102 +497,16 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash-resources.sh\"\n";
-			showEnvVarsInLog = 0;
-		};
-		538F0530BD355DE69016FC8D /* [CP] Check Pods Manifest.lock */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-			);
-			inputPaths = (
-				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
-				"${PODS_ROOT}/Manifest.lock",
-			);
-			name = "[CP] Check Pods Manifest.lock";
-			outputFileListPaths = (
-			);
-			outputPaths = (
-				"$(DERIVED_FILE_DIR)/Pods-ExpensifyCash-ExpensifyCashTests-checkManifestLockResult.txt",
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
-			showEnvVarsInLog = 0;
-		};
-		5717025076C7AEA43883A0AC /* [CP-User] [RNFB] Crashlytics Configuration */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			name = "[CP-User] [RNFB] Crashlytics Configuration";
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "#!/usr/bin/env bash\n#\n# Copyright (c) 2016-present Invertase Limited & Contributors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this library except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nset -e\n\nif [[ ${PODS_ROOT} ]]; then\n  echo \"info: Exec FirebaseCrashlytics Run from Pods\"\n  \"${PODS_ROOT}/FirebaseCrashlytics/run\"\nelse\n  echo \"info: Exec FirebaseCrashlytics Run from framework\"\n  \"${PROJECT_DIR}/FirebaseCrashlytics.framework/run\"\nfi\n";
-		};
-		8575AEF2E98CE400DE51E589 /* [CP] Embed Pods Frameworks */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash-frameworks.sh",
-				"${PODS_XCFRAMEWORKS_BUILD_DIR}/Onfido/Onfido.framework/Onfido",
-				"${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL/OpenSSL.framework/OpenSSL",
-				"${PODS_XCFRAMEWORKS_BUILD_DIR}/LinkKit/LinkKit.framework/LinkKit",
-			);
-			name = "[CP] Embed Pods Frameworks";
-			outputPaths = (
-				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Onfido.framework",
-				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework",
-				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LinkKit.framework",
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash-frameworks.sh\"\n";
-			showEnvVarsInLog = 0;
-		};
-		BD50DAA2FC45BE14BFB945D0 /* [CP] Check Pods Manifest.lock */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-			);
-			inputPaths = (
-				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
-				"${PODS_ROOT}/Manifest.lock",
-			);
-			name = "[CP] Check Pods Manifest.lock";
-			outputFileListPaths = (
-			);
-			outputPaths = (
-				"$(DERIVED_FILE_DIR)/Pods-ExpensifyCash-checkManifestLockResult.txt",
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash-ExpensifyCashTests/Pods-ExpensifyCash-ExpensifyCashTests-resources.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
-		CF6C6C97851DBF01CDAE664E /* [CP-User] [RNFB] Core Configuration */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			name = "[CP-User] [RNFB] Core Configuration";
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "#!/usr/bin/env bash\n#\n# Copyright (c) 2016-present Invertase Limited & Contributors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this library except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nset -e\n\n_MAX_LOOKUPS=2;\n_SEARCH_RESULT=''\n_RN_ROOT_EXISTS=''\n_CURRENT_LOOKUPS=1\n_JSON_ROOT=\"'react-native'\"\n_JSON_FILE_NAME='firebase.json'\n_JSON_OUTPUT_BASE64='e30=' # { }\n_CURRENT_SEARCH_DIR=${PROJECT_DIR}\n_PLIST_BUDDY=/usr/libexec/PlistBuddy\n_TARGET_PLIST=\"${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}\"\n_DSYM_PLIST=\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist\"\n\n# plist arrays\n_PLIST_ENTRY_KEYS=()\n_PLIST_ENTRY_TYPES=()\n_PLIST_ENTRY_VALUES=()\n\nfunction setPlistValue {\n  echo \"info:      setting plist entry '$1' of type '$2' in file '$4'\"\n  ${_PLIST_BUDDY} -c \"Add :$1 $2 '$3'\" $4 || echo \"info:      '$1' already exists\"\n}\n\nfunction getFirebaseJsonKeyValue () {\n  if [[ ${_RN_ROOT_EXISTS} ]]; then\n    ruby -e \"require 'rubygems';require 'json'; output=JSON.parse('$1'); puts output[$_JSON_ROOT]['$2']\"\n  else\n    echo \"\"\n  fi;\n}\n\nfunction jsonBoolToYesNo () {\n  if [[ $1 == \"false\" ]]; then\n    echo \"NO\"\n  elif [[ $1 == \"true\" ]]; then\n    echo \"YES\"\n  else echo \"NO\"\n  fi\n}\n\necho \"info: -> RNFB build script started\"\necho \"info: 1) Locating ${_JSON_FILE_NAME} file:\"\n\nif [[ -z ${_CURRENT_SEARCH_DIR} ]]; then\n  _CURRENT_SEARCH_DIR=$(pwd)\nfi;\n\nwhile true; do\n  _CURRENT_SEARCH_DIR=$(dirname \"$_CURRENT_SEARCH_DIR\")\n  if [[ \"$_CURRENT_SEARCH_DIR\" == \"/\" ]] || [[ ${_CURRENT_LOOKUPS} -gt ${_MAX_LOOKUPS} ]]; then break; fi;\n  echo \"info:      ($_CURRENT_LOOKUPS of $_MAX_LOOKUPS) Searching in '$_CURRENT_SEARCH_DIR' for a ${_JSON_FILE_NAME} file.\"\n  _SEARCH_RESULT=$(find \"$_CURRENT_SEARCH_DIR\" -maxdepth 2 -name ${_JSON_FILE_NAME} -print | head -n 1)\n  if [[ ${_SEARCH_RESULT} ]]; then\n    echo \"info:      ${_JSON_FILE_NAME} found at $_SEARCH_RESULT\"\n    break;\n  fi;\n  _CURRENT_LOOKUPS=$((_CURRENT_LOOKUPS+1))\ndone\n\nif [[ ${_SEARCH_RESULT} ]]; then\n  _JSON_OUTPUT_RAW=$(cat \"${_SEARCH_RESULT}\")\n  _RN_ROOT_EXISTS=$(ruby -e \"require 'rubygems';require 'json'; output=JSON.parse('$_JSON_OUTPUT_RAW'); puts output[$_JSON_ROOT]\" || echo '')\n\n  if [[ ${_RN_ROOT_EXISTS} ]]; then\n    _JSON_OUTPUT_BASE64=$(python -c 'import json,sys,base64;print(base64.b64encode(json.dumps(json.loads(open('\"'${_SEARCH_RESULT}'\"').read())['${_JSON_ROOT}'])))' || echo \"e30=\")\n  fi\n\n  _PLIST_ENTRY_KEYS+=(\"firebase_json_raw\")\n  _PLIST_ENTRY_TYPES+=(\"string\")\n  _PLIST_ENTRY_VALUES+=(\"$_JSON_OUTPUT_BASE64\")\n\n  # config.messaging_auto_init_enabled\n  _MESSAGING_AUTO_INIT=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"messaging_auto_init_enabled\")\n  if [[ $_MESSAGING_AUTO_INIT ]]; then\n    _PLIST_ENTRY_KEYS+=(\"FirebaseMessagingAutoInitEnabled\")\n    _PLIST_ENTRY_TYPES+=(\"bool\")\n    _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_MESSAGING_AUTO_INIT\")\")\n  fi\n\n  # config.crashlytics_disable_auto_disabler - undocumented for now - mainly for debugging, document if becomes useful\n  _CRASHLYTICS_AUTO_DISABLE_ENABLED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"crashlytics_disable_auto_disabler\")\n  if [[ $_CRASHLYTICS_AUTO_DISABLE_ENABLED == \"true\" ]]; then\n    echo \"Disabled Crashlytics auto disabler.\" # do nothing\n  else\n    _PLIST_ENTRY_KEYS+=(\"FirebaseCrashlyticsCollectionEnabled\")\n    _PLIST_ENTRY_TYPES+=(\"bool\")\n    _PLIST_ENTRY_VALUES+=(\"NO\")\n  fi\n\n  # config.admob_delay_app_measurement_init\n  _ADMOB_DELAY_APP_MEASUREMENT=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"admob_delay_app_measurement_init\")\n  if [[ $_ADMOB_DELAY_APP_MEASUREMENT == \"true\" ]]; then\n    _PLIST_ENTRY_KEYS+=(\"GADDelayAppMeasurementInit\")\n    _PLIST_ENTRY_TYPES+=(\"bool\")\n    _PLIST_ENTRY_VALUES+=(\"YES\")\n  fi\n\n  # config.admob_ios_app_id\n  _ADMOB_IOS_APP_ID=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"admob_ios_app_id\")\n  if [[ $_ADMOB_IOS_APP_ID ]]; then\n    _PLIST_ENTRY_KEYS+=(\"GADApplicationIdentifier\")\n    _PLIST_ENTRY_TYPES+=(\"string\")\n    _PLIST_ENTRY_VALUES+=(\"$_ADMOB_IOS_APP_ID\")\n  fi\nelse\n  _PLIST_ENTRY_KEYS+=(\"firebase_json_raw\")\n  _PLIST_ENTRY_TYPES+=(\"string\")\n  _PLIST_ENTRY_VALUES+=(\"$_JSON_OUTPUT_BASE64\")\n  echo \"warning:   A firebase.json file was not found, whilst this file is optional it is recommended to include it to configure firebase services in React Native Firebase.\"\nfi;\n\necho \"info: 2) Injecting Info.plist entries: \"\n\n# Log out the keys we're adding\nfor i in \"${!_PLIST_ENTRY_KEYS[@]}\"; do\n  echo \"    ->  $i) ${_PLIST_ENTRY_KEYS[$i]}\" \"${_PLIST_ENTRY_TYPES[$i]}\" \"${_PLIST_ENTRY_VALUES[$i]}\"\ndone\n\nfor plist in \"${_TARGET_PLIST}\" \"${_DSYM_PLIST}\" ; do\n  if [[ -f \"${plist}\" ]]; then\n\n    # paths with spaces break the call to setPlistValue. temporarily modify\n    # the shell internal field separator variable (IFS), which normally\n    # includes spaces, to consist only of line breaks\n    oldifs=$IFS\n    IFS=\"\n\"\n\n    for i in \"${!_PLIST_ENTRY_KEYS[@]}\"; do\n      setPlistValue \"${_PLIST_ENTRY_KEYS[$i]}\" \"${_PLIST_ENTRY_TYPES[$i]}\" \"${_PLIST_ENTRY_VALUES[$i]}\" \"${plist}\"\n    done\n\n    # restore the original internal field separator value\n    IFS=$oldifs\n  else\n    echo \"warning:   A Info.plist build output file was not found (${plist})\"\n  fi\ndone\n\necho \"info: <- RNFB build script finished\"\n";
-		};
-		D91BC49ED9E5B6C37CAABCC6 /* [CP] Copy Pods Resources */ = {
+		2FF33D22F22E13C0294AF784 /* [CP] Copy Pods Resources */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash-ExpensifyCashTests/Pods-ExpensifyCash-ExpensifyCashTests-resources.sh",
+				"${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash-resources.sh",
 				"${PODS_ROOT}/Airship/Airship/AirshipAutomation/Resources/UAAutomationActions.plist",
 				"${PODS_ROOT}/Airship/Airship/AirshipAutomation/Resources/UAInAppMessageBannerContentView.xib",
 				"${PODS_ROOT}/Airship/Airship/AirshipAutomation/Resources/UAInAppMessageBannerView.xib",
@@ -689,10 +625,10 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash-ExpensifyCashTests/Pods-ExpensifyCash-ExpensifyCashTests-resources.sh\"\n";
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash-resources.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
-		DC5669E1DEB80DD839FDB293 /* [CP] Embed Pods Frameworks */ = {
+		508FBBA985FA02D6C17543EF /* [CP] Embed Pods Frameworks */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
@@ -714,6 +650,70 @@
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash-ExpensifyCashTests/Pods-ExpensifyCash-ExpensifyCashTests-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
+		8DFA5A00696B687F79C95016 /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-ExpensifyCash-ExpensifyCashTests-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
+		98C853189A534B46B0295A00 /* [CP-User] [RNFB] Core Configuration */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			name = "[CP-User] [RNFB] Core Configuration";
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "#!/usr/bin/env bash\n#\n# Copyright (c) 2016-present Invertase Limited & Contributors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this library except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nset -e\n\n_MAX_LOOKUPS=2;\n_SEARCH_RESULT=''\n_RN_ROOT_EXISTS=''\n_CURRENT_LOOKUPS=1\n_JSON_ROOT=\"'react-native'\"\n_JSON_FILE_NAME='firebase.json'\n_JSON_OUTPUT_BASE64='e30=' # { }\n_CURRENT_SEARCH_DIR=${PROJECT_DIR}\n_PLIST_BUDDY=/usr/libexec/PlistBuddy\n_TARGET_PLIST=\"${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}\"\n_DSYM_PLIST=\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist\"\n\n# plist arrays\n_PLIST_ENTRY_KEYS=()\n_PLIST_ENTRY_TYPES=()\n_PLIST_ENTRY_VALUES=()\n\nfunction setPlistValue {\n  echo \"info:      setting plist entry '$1' of type '$2' in file '$4'\"\n  ${_PLIST_BUDDY} -c \"Add :$1 $2 '$3'\" $4 || echo \"info:      '$1' already exists\"\n}\n\nfunction getFirebaseJsonKeyValue () {\n  if [[ ${_RN_ROOT_EXISTS} ]]; then\n    ruby -e \"require 'rubygems';require 'json'; output=JSON.parse('$1'); puts output[$_JSON_ROOT]['$2']\"\n  else\n    echo \"\"\n  fi;\n}\n\nfunction jsonBoolToYesNo () {\n  if [[ $1 == \"false\" ]]; then\n    echo \"NO\"\n  elif [[ $1 == \"true\" ]]; then\n    echo \"YES\"\n  else echo \"NO\"\n  fi\n}\n\necho \"info: -> RNFB build script started\"\necho \"info: 1) Locating ${_JSON_FILE_NAME} file:\"\n\nif [[ -z ${_CURRENT_SEARCH_DIR} ]]; then\n  _CURRENT_SEARCH_DIR=$(pwd)\nfi;\n\nwhile true; do\n  _CURRENT_SEARCH_DIR=$(dirname \"$_CURRENT_SEARCH_DIR\")\n  if [[ \"$_CURRENT_SEARCH_DIR\" == \"/\" ]] || [[ ${_CURRENT_LOOKUPS} -gt ${_MAX_LOOKUPS} ]]; then break; fi;\n  echo \"info:      ($_CURRENT_LOOKUPS of $_MAX_LOOKUPS) Searching in '$_CURRENT_SEARCH_DIR' for a ${_JSON_FILE_NAME} file.\"\n  _SEARCH_RESULT=$(find \"$_CURRENT_SEARCH_DIR\" -maxdepth 2 -name ${_JSON_FILE_NAME} -print | head -n 1)\n  if [[ ${_SEARCH_RESULT} ]]; then\n    echo \"info:      ${_JSON_FILE_NAME} found at $_SEARCH_RESULT\"\n    break;\n  fi;\n  _CURRENT_LOOKUPS=$((_CURRENT_LOOKUPS+1))\ndone\n\nif [[ ${_SEARCH_RESULT} ]]; then\n  _JSON_OUTPUT_RAW=$(cat \"${_SEARCH_RESULT}\")\n  _RN_ROOT_EXISTS=$(ruby -e \"require 'rubygems';require 'json'; output=JSON.parse('$_JSON_OUTPUT_RAW'); puts output[$_JSON_ROOT]\" || echo '')\n\n  if [[ ${_RN_ROOT_EXISTS} ]]; then\n    _JSON_OUTPUT_BASE64=$(python -c 'import json,sys,base64;print(base64.b64encode(json.dumps(json.loads(open('\"'${_SEARCH_RESULT}'\"').read())['${_JSON_ROOT}'])))' || echo \"e30=\")\n  fi\n\n  _PLIST_ENTRY_KEYS+=(\"firebase_json_raw\")\n  _PLIST_ENTRY_TYPES+=(\"string\")\n  _PLIST_ENTRY_VALUES+=(\"$_JSON_OUTPUT_BASE64\")\n\n  # config.messaging_auto_init_enabled\n  _MESSAGING_AUTO_INIT=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"messaging_auto_init_enabled\")\n  if [[ $_MESSAGING_AUTO_INIT ]]; then\n    _PLIST_ENTRY_KEYS+=(\"FirebaseMessagingAutoInitEnabled\")\n    _PLIST_ENTRY_TYPES+=(\"bool\")\n    _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_MESSAGING_AUTO_INIT\")\")\n  fi\n\n  # config.crashlytics_disable_auto_disabler - undocumented for now - mainly for debugging, document if becomes useful\n  _CRASHLYTICS_AUTO_DISABLE_ENABLED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"crashlytics_disable_auto_disabler\")\n  if [[ $_CRASHLYTICS_AUTO_DISABLE_ENABLED == \"true\" ]]; then\n    echo \"Disabled Crashlytics auto disabler.\" # do nothing\n  else\n    _PLIST_ENTRY_KEYS+=(\"FirebaseCrashlyticsCollectionEnabled\")\n    _PLIST_ENTRY_TYPES+=(\"bool\")\n    _PLIST_ENTRY_VALUES+=(\"NO\")\n  fi\n\n  # config.admob_delay_app_measurement_init\n  _ADMOB_DELAY_APP_MEASUREMENT=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"admob_delay_app_measurement_init\")\n  if [[ $_ADMOB_DELAY_APP_MEASUREMENT == \"true\" ]]; then\n    _PLIST_ENTRY_KEYS+=(\"GADDelayAppMeasurementInit\")\n    _PLIST_ENTRY_TYPES+=(\"bool\")\n    _PLIST_ENTRY_VALUES+=(\"YES\")\n  fi\n\n  # config.admob_ios_app_id\n  _ADMOB_IOS_APP_ID=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"admob_ios_app_id\")\n  if [[ $_ADMOB_IOS_APP_ID ]]; then\n    _PLIST_ENTRY_KEYS+=(\"GADApplicationIdentifier\")\n    _PLIST_ENTRY_TYPES+=(\"string\")\n    _PLIST_ENTRY_VALUES+=(\"$_ADMOB_IOS_APP_ID\")\n  fi\nelse\n  _PLIST_ENTRY_KEYS+=(\"firebase_json_raw\")\n  _PLIST_ENTRY_TYPES+=(\"string\")\n  _PLIST_ENTRY_VALUES+=(\"$_JSON_OUTPUT_BASE64\")\n  echo \"warning:   A firebase.json file was not found, whilst this file is optional it is recommended to include it to configure firebase services in React Native Firebase.\"\nfi;\n\necho \"info: 2) Injecting Info.plist entries: \"\n\n# Log out the keys we're adding\nfor i in \"${!_PLIST_ENTRY_KEYS[@]}\"; do\n  echo \"    ->  $i) ${_PLIST_ENTRY_KEYS[$i]}\" \"${_PLIST_ENTRY_TYPES[$i]}\" \"${_PLIST_ENTRY_VALUES[$i]}\"\ndone\n\nfor plist in \"${_TARGET_PLIST}\" \"${_DSYM_PLIST}\" ; do\n  if [[ -f \"${plist}\" ]]; then\n\n    # paths with spaces break the call to setPlistValue. temporarily modify\n    # the shell internal field separator variable (IFS), which normally\n    # includes spaces, to consist only of line breaks\n    oldifs=$IFS\n    IFS=\"\n\"\n\n    for i in \"${!_PLIST_ENTRY_KEYS[@]}\"; do\n      setPlistValue \"${_PLIST_ENTRY_KEYS[$i]}\" \"${_PLIST_ENTRY_TYPES[$i]}\" \"${_PLIST_ENTRY_VALUES[$i]}\" \"${plist}\"\n    done\n\n    # restore the original internal field separator value\n    IFS=$oldifs\n  else\n    echo \"warning:   A Info.plist build output file was not found (${plist})\"\n  fi\ndone\n\necho \"info: <- RNFB build script finished\"\n";
+		};
+		9ADAD62C841619370715F04D /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-ExpensifyCash-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
+		E0A3A156B5B4C0811DDF7822 /* [CP-User] [RNFB] Crashlytics Configuration */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			name = "[CP-User] [RNFB] Crashlytics Configuration";
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "#!/usr/bin/env bash\n#\n# Copyright (c) 2016-present Invertase Limited & Contributors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this library except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nset -e\n\nif [[ ${PODS_ROOT} ]]; then\n  echo \"info: Exec FirebaseCrashlytics Run from Pods\"\n  \"${PODS_ROOT}/FirebaseCrashlytics/run\"\nelse\n  echo \"info: Exec FirebaseCrashlytics Run from framework\"\n  \"${PROJECT_DIR}/FirebaseCrashlytics.framework/run\"\nfi\n";
+		};
 		FD10A7F022414F080027D42C /* Start Packager */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
@@ -769,7 +769,7 @@
 /* Begin XCBuildConfiguration section */
 		00E356F61AD99517003FC87E /* Debug */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = B82386231652D749850CFC70 /* Pods-ExpensifyCash-ExpensifyCashTests.debug.xcconfig */;
+			baseConfigurationReference = 8505C557B697659B3983EF08 /* Pods-ExpensifyCash-ExpensifyCashTests.debug.xcconfig */;
 			buildSettings = {
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				BUNDLE_LOADER = "$(TEST_HOST)";
@@ -794,7 +794,7 @@
 		};
 		00E356F71AD99517003FC87E /* Release */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = D111222CBD2088E51A5BB624 /* Pods-ExpensifyCash-ExpensifyCashTests.release.xcconfig */;
+			baseConfigurationReference = A9454D0E01D17128C0732883 /* Pods-ExpensifyCash-ExpensifyCashTests.release.xcconfig */;
 			buildSettings = {
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				BUNDLE_LOADER = "$(TEST_HOST)";
@@ -817,15 +817,15 @@
 		};
 		13B07F941A680F5B00A75B9A /* Debug */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 40EE174FE0E5010DA25F3180 /* Pods-ExpensifyCash.debug.xcconfig */;
+			baseConfigurationReference = 6F9F2F6F4E0F0090A238B760 /* Pods-ExpensifyCash.debug.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = ExpensifyCash/Chat.entitlements;
-				CODE_SIGN_IDENTITY = "iPhone Distribution";
-				CODE_SIGN_STYLE = Manual;
+				CODE_SIGN_IDENTITY = "Apple Development";
+				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 3;
-				DEVELOPMENT_TEAM = 368M544MTT;
+				DEVELOPMENT_TEAM = "";
 				ENABLE_BITCODE = NO;
 				"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
 				INFOPLIST_FILE = ExpensifyCash/Info.plist;
@@ -839,7 +839,7 @@
 				);
 				PRODUCT_BUNDLE_IDENTIFIER = com.chat.expensify.chat;
 				PRODUCT_NAME = Expensify.cash;
-				PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore;
+				PROVISIONING_PROFILE_SPECIFIER = "";
 				SWIFT_OBJC_BRIDGING_HEADER = "ExpensifyCash-Bridging-Header.h";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_VERSION = 5.0;
@@ -850,15 +850,15 @@
 		};
 		13B07F951A680F5B00A75B9A /* Release */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 5E0275D64694B453A3EE297D /* Pods-ExpensifyCash.release.xcconfig */;
+			baseConfigurationReference = 51191C9E80935A80099F67B4 /* Pods-ExpensifyCash.release.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = ExpensifyCash/Chat.entitlements;
-				CODE_SIGN_IDENTITY = "iPhone Distribution";
-				CODE_SIGN_STYLE = Manual;
+				CODE_SIGN_IDENTITY = "Apple Development";
+				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 3;
-				DEVELOPMENT_TEAM = 368M544MTT;
+				DEVELOPMENT_TEAM = "";
 				"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
 				INFOPLIST_FILE = ExpensifyCash/Info.plist;
 				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
@@ -871,7 +871,7 @@
 				);
 				PRODUCT_BUNDLE_IDENTIFIER = com.chat.expensify.chat;
 				PRODUCT_NAME = Expensify.cash;
-				PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore;
+				PROVISIONING_PROFILE_SPECIFIER = "";
 				SWIFT_OBJC_BRIDGING_HEADER = "ExpensifyCash-Bridging-Header.h";
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2";
diff --git a/ios/ExpensifyCash/AppDelegate.m b/ios/ExpensifyCash/AppDelegate.m
index 0138f2b3cc4c..0a2a05ceda12 100644
--- a/ios/ExpensifyCash/AppDelegate.m
+++ b/ios/ExpensifyCash/AppDelegate.m
@@ -9,6 +9,7 @@
 #import "RNBootSplash.h"
 
 #import <UserNotifications/UserNotifications.h>
+#import <RNCPushNotificationIOS.h>
 
 #ifdef FB_SONARKIT_ENABLED
 #import <FlipperKit/FlipperClient.h>
@@ -86,4 +87,36 @@ - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull N
                     restorationHandler:restorationHandler];
 }
 
+//Called when a notification is delivered to a foreground app.
+-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
+{
+  completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
+}
+
+/*=== START react-native-push-notification-ios configs ===*/
+// Required for the register event.
+- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
+{
+ [RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
+}
+// Required for the notification event. You must call the completion handler after handling the remote notification.
+- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
+fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
+{
+  [RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
+}
+// Required for the registrationError event.
+- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
+{
+ [RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
+}
+// Required for localNotification event
+- (void)userNotificationCenter:(UNUserNotificationCenter *)center
+didReceiveNotificationResponse:(UNNotificationResponse *)response
+         withCompletionHandler:(void (^)(void))completionHandler
+{
+  [RNCPushNotificationIOS didReceiveNotificationResponse:response];
+}
+/*=== END react-native-push-notification-ios configs ===*/
+
 @end
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 8f4aa1dc3ac5..e2e566a3d416 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -444,6 +444,8 @@ PODS:
     - React-Core
   - RNCPicker (1.9.11):
     - React-Core
+  - RNCPushNotificationIOS (1.8.0):
+    - React-Core
   - RNFBAnalytics (7.6.8):
     - Firebase/Analytics (~> 6.34.0)
     - React-Core
@@ -568,6 +570,7 @@ DEPENDENCIES:
   - "RNCClipboard (from `../node_modules/@react-native-community/clipboard`)"
   - "RNCMaskedView (from `../node_modules/@react-native-masked-view/masked-view`)"
   - "RNCPicker (from `../node_modules/@react-native-picker/picker`)"
+  - "RNCPushNotificationIOS (from `../node_modules/@react-native-community/push-notification-ios`)"
   - "RNFBAnalytics (from `../node_modules/@react-native-firebase/analytics`)"
   - "RNFBApp (from `../node_modules/@react-native-firebase/app`)"
   - "RNFBCrashlytics (from `../node_modules/@react-native-firebase/crashlytics`)"
@@ -701,6 +704,8 @@ EXTERNAL SOURCES:
     :path: "../node_modules/@react-native-masked-view/masked-view"
   RNCPicker:
     :path: "../node_modules/@react-native-picker/picker"
+  RNCPushNotificationIOS:
+    :path: "../node_modules/@react-native-community/push-notification-ios"
   RNFBAnalytics:
     :path: "../node_modules/@react-native-firebase/analytics"
   RNFBApp:
@@ -794,6 +799,7 @@ SPEC CHECKSUMS:
   RNCClipboard: 5e299c6df8e0c98f3d7416b86ae563d3a9f768a3
   RNCMaskedView: 138134c4d8a9421b4f2bf39055a79aa05c2d47b1
   RNCPicker: 6780c753e9e674065db90d9c965920516402579d
+  RNCPushNotificationIOS: 5b1cf9ad2aaa107ecb92d5d2d7005ba521b2b97a
   RNFBAnalytics: 2dc4dd9e2445faffca041b10447a23a71dcdabf8
   RNFBApp: 7eacc7da7ab19f96c05e434017d44a9f09410da8
   RNFBCrashlytics: 4870c14cf8833053b6b5648911abefe1923854d2
diff --git a/package-lock.json b/package-lock.json
index b9dce013edf7..69933e794502 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5791,6 +5791,14 @@
       "resolved": "https://registry.npmjs.org/@react-native-community/progress-view/-/progress-view-1.2.3.tgz",
       "integrity": "sha512-CW7eOhxduIxA723aZlKMOnBEz1o5Cjo5ibMNsf81TcjNqtsamRHm8jFS98za7t5P7XdhM0MhzkbaS90cwOlN+Q=="
     },
+    "@react-native-community/push-notification-ios": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/@react-native-community/push-notification-ios/-/push-notification-ios-1.8.0.tgz",
+      "integrity": "sha512-vxvkeampafjmtDoQBN8Q4azP21l6cMX93+OQZemyIWZmG++OjCVDQVitobf/kWLm5zyGwdylejbpMGo75qo7rA==",
+      "requires": {
+        "invariant": "^2.2.4"
+      }
+    },
     "@react-native-firebase/analytics": {
       "version": "7.6.8",
       "resolved": "https://registry.npmjs.org/@react-native-firebase/analytics/-/analytics-7.6.8.tgz",
@@ -23328,6 +23336,11 @@
       "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
       "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
     },
+    "ios-deploy": {
+      "version": "1.11.4",
+      "resolved": "https://registry.npmjs.org/ios-deploy/-/ios-deploy-1.11.4.tgz",
+      "integrity": "sha512-NZ96/s7klyWySKTI8rTU+vXEIxIMrv6K+7j5VMcqUVShaAUdDX+Ov4nVdSStYOAGFVpl8q56SpAwjEDIvBrswQ=="
+    },
     "ip": {
       "version": "1.1.5",
       "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
@@ -33973,6 +33986,11 @@
         "tsc": "^1.20150623.0"
       }
     },
+    "react-native-push-notification": {
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/react-native-push-notification/-/react-native-push-notification-7.3.1.tgz",
+      "integrity": "sha512-5kSKPvDU23uZRmzgKTsGhbwGNvB2tidu1VnInBHP53ZD0VEPSBl5fbpuTfHH98ED+Gp1SCcT2/e6bJWkIspKvg=="
+    },
     "react-native-reanimated": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-2.1.0.tgz",
@@ -38451,9 +38469,9 @@
       }
     },
     "urbanairship-react-native": {
-      "version": "11.0.1",
-      "resolved": "https://registry.npmjs.org/urbanairship-react-native/-/urbanairship-react-native-11.0.1.tgz",
-      "integrity": "sha512-QNXz655hBveFSv5kMFivhUkpHopt0ojIFCWEP+H0vssKjrO8z0xDmlM6Gd4aeUT63nwTaAUbH7zU8qTLFFrs+w=="
+      "version": "11.0.2",
+      "resolved": "https://registry.npmjs.org/urbanairship-react-native/-/urbanairship-react-native-11.0.2.tgz",
+      "integrity": "sha512-CH5frL9gVAeRFuJm61MC5nAFsfGu9pxT94jQwjtTKqrTlwd/EMoFgYrV1ITuub70MInCD3OFP0FDA3H8YJdZtQ=="
     },
     "uri-js": {
       "version": "4.4.0",
diff --git a/package.json b/package.json
index 08a793391d62..eccc4aed9ef1 100644
--- a/package.json
+++ b/package.json
@@ -44,6 +44,7 @@
     "@react-native-community/netinfo": "^5.9.10",
     "@react-native-community/progress-bar-android": "^1.0.4",
     "@react-native-community/progress-view": "^1.2.3",
+    "@react-native-community/push-notification-ios": "^1.8.0",
     "@react-native-firebase/analytics": "^7.6.7",
     "@react-native-firebase/app": "^8.4.5",
     "@react-native-firebase/crashlytics": "^8.4.9",
@@ -62,6 +63,7 @@
     "expensify-common": "git://github.com/Expensify/expensify-common.git#c3465bf615390a2844087ec7f2343b0607ea484c",
     "file-loader": "^6.0.0",
     "html-entities": "^1.3.1",
+    "ios-deploy": "^1.11.4",
     "lodash": "4.17.21",
     "metro-config": "^0.64.0",
     "moment": "^2.27.0",
@@ -85,6 +87,7 @@
     "react-native-permissions": "^3.0.1",
     "react-native-picker-select": "8.0.4",
     "react-native-plaid-link-sdk": "^7.0.5",
+    "react-native-push-notification": "^7.3.1",
     "react-native-reanimated": "^2.1.0",
     "react-native-render-html": "^6.0.0-alpha.10",
     "react-native-safe-area-context": "^3.1.4",
@@ -97,7 +100,7 @@
     "rn-fetch-blob": "^0.12.0",
     "save": "^2.4.0",
     "underscore": "^1.10.2",
-    "urbanairship-react-native": "^11.0.1"
+    "urbanairship-react-native": "^11.0.2"
   },
   "devDependencies": {
     "@actions/core": "^1.2.6",
diff --git a/src/CONST.js b/src/CONST.js
index dd1005bc037a..79108e29a09c 100755
--- a/src/CONST.js
+++ b/src/CONST.js
@@ -340,6 +340,12 @@ const CONST = {
         },
     },
 
+    NOTIFICATION_PREFERENCE: {
+        ALWAYS: 'always',
+        DAILY: 'daily',
+        MUTE: 'mute',
+    },
+
     REGEX: {
         US_PHONE: /^\+1\d{10}$/,
         PHONE_E164_PLUS: /^\+?[1-9]\d{1,14}$/,
diff --git a/src/Expensify.js b/src/Expensify.js
index 421658fb55ee..e8d2b0d145fd 100644
--- a/src/Expensify.js
+++ b/src/Expensify.js
@@ -2,15 +2,12 @@ import lodashGet from 'lodash/get';
 import PropTypes from 'prop-types';
 import React, {PureComponent} from 'react';
 import {View, AppState} from 'react-native';
-import Onyx, {withOnyx} from 'react-native-onyx';
+import {withOnyx} from 'react-native-onyx';
 
 import BootSplash from './libs/BootSplash';
-import listenToStorageEvents from './libs/listenToStorageEvents';
 import * as ActiveClientManager from './libs/ActiveClientManager';
 import ONYXKEYS from './ONYXKEYS';
-import CONST from './CONST';
 import NavigationRoot from './libs/Navigation/NavigationRoot';
-import Log from './libs/Log';
 import migrateOnyx from './libs/migrateOnyx';
 import styles from './styles/styles';
 import PushNotification from './libs/Notification/PushNotification';
@@ -21,32 +18,6 @@ import {growlRef} from './libs/Growl';
 import Navigation from './libs/Navigation/Navigation';
 import ROUTES from './ROUTES';
 
-// Initialize the store when the app loads for the first time
-Onyx.init({
-    keys: ONYXKEYS,
-    safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
-    initialKeyStates: {
-
-        // Clear any loading and error messages so they do not appear on app startup
-        [ONYXKEYS.SESSION]: {loading: false, shouldShowComposeInput: true},
-        [ONYXKEYS.ACCOUNT]: CONST.DEFAULT_ACCOUNT_DATA,
-        [ONYXKEYS.NETWORK]: {isOffline: false},
-        [ONYXKEYS.IOU]: {
-            loading: false, error: false, creatingIOUTransaction: false, isRetrievingCurrency: false,
-        },
-    },
-    registerStorageEventListener: (onStorageEvent) => {
-        listenToStorageEvents(onStorageEvent);
-    },
-});
-Onyx.registerLogger(({level, message}) => {
-    if (level === 'alert') {
-        Log.alert(message, 0, {}, false);
-    } else {
-        Log.client(message);
-    }
-});
-
 const propTypes = {
     /* Onyx Props */
 
diff --git a/src/libs/Notification/LocalNotification/BrowserNotifications.js b/src/libs/Notification/LocalNotification/BrowserNotifications.js
deleted file mode 100644
index f5e128d3eec1..000000000000
--- a/src/libs/Notification/LocalNotification/BrowserNotifications.js
+++ /dev/null
@@ -1,136 +0,0 @@
-// Web and desktop implementation only. Do not import for direct use. Use LocalNotification.
-import Str from 'expensify-common/lib/str';
-import Onyx from 'react-native-onyx';
-import focusApp from './focusApp';
-import EXPENSIFY_ICON_URL from '../../../../assets/images/expensify-logo-round-clearspace.png';
-import ONYXKEYS from '../../../ONYXKEYS';
-
-const DEFAULT_DELAY = 4000;
-
-/**
- * Checks if the user has granted permission to show browser notifications
- *
- * @return {Promise}
- */
-function canUseBrowserNotifications() {
-    return new Promise((resolve) => {
-        // They have no browser notifications so we can't use this feature
-        if (!window.Notification) {
-            return resolve(false);
-        }
-
-        // Check if they previously granted or denied us access to send a notification
-        const permissionGranted = Notification.permission === 'granted';
-
-        if (permissionGranted || Notification.permission === 'denied') {
-            return resolve(permissionGranted);
-        }
-
-        // Check their global preferences for browser notifications and ask permission if they have none
-        Notification.requestPermission()
-            .then((status) => {
-                resolve(status === 'granted');
-            });
-    });
-}
-
-/**
- * Light abstraction around browser push notifications.
- * Checks for permission before determining whether to send.
- *
- * @param {Object} params
- * @param {String} params.title
- * @param {String} params.body
- * @param {String} [params.icon] Default to Expensify logo
- * @param {Number} [params.delay]
- * @param {Function} [params.onClick]
- * @param {String} [params.tag]
- *
- * @return {Promise} - resolves with Notification object or undefined
- */
-function push({
-    title,
-    body,
-    delay = DEFAULT_DELAY,
-    onClick = () => {},
-    tag = '',
-    icon = EXPENSIFY_ICON_URL,
-}) {
-    return new Promise((resolve) => {
-        if (!title || !body) {
-            throw new Error('BrowserNotification must include title and body parameter.');
-        }
-
-        canUseBrowserNotifications().then((canUseNotifications) => {
-            if (!canUseNotifications) {
-                resolve();
-                return;
-            }
-
-            const notification = new Notification(title, {
-                body,
-                icon,
-                tag,
-            });
-
-            // If we pass in a delay param greater than 0 the notification
-            // will auto-close after the specified time.
-            if (delay > 0) {
-                setTimeout(notification.close.bind(notification), delay);
-            }
-
-            notification.onclick = (event) => {
-                event.preventDefault();
-                onClick();
-                window.parent.focus();
-                window.focus();
-                focusApp();
-                notification.close();
-            };
-
-            resolve(notification);
-        });
-    });
-}
-
-/**
- * BrowserNotification
- * @namespace
- */
-export default {
-    /**
-     * Create a report comment notification
-     *
-     * @param {Object} params
-     * @param {Object} params.reportAction
-     * @param {Function} params.onClick
-     */
-    pushReportCommentNotification({reportAction, onClick}) {
-        const {person, message} = reportAction;
-        const plainTextPerson = Str.htmlDecode(person.map(f => f.text).join());
-
-        // Specifically target the comment part of the message
-        const plainTextMessage = Str.htmlDecode((message.find(f => f.type === 'COMMENT') || {}).text);
-
-        push({
-            title: `New message from ${plainTextPerson}`,
-            body: plainTextMessage,
-            delay: 0,
-            onClick,
-        });
-    },
-
-    /**
-     * Create a notification to indicate that an update is available.
-     */
-    pushUpdateAvailableNotification() {
-        push({
-            title: 'Update available',
-            body: 'A new version of Expensify.cash is available!',
-            delay: 0,
-            onClick: () => {
-                Onyx.merge(ONYXKEYS.UPDATE_AVAILABLE, true);
-            },
-        });
-    },
-};
diff --git a/src/libs/Notification/LocalNotification/LocalNotification.js b/src/libs/Notification/LocalNotification/LocalNotification.js
new file mode 100644
index 000000000000..793a9def4c6a
--- /dev/null
+++ b/src/libs/Notification/LocalNotification/LocalNotification.js
@@ -0,0 +1,26 @@
+import EXPENSIFY_ICON_URL from '../../../../assets/images/expensify-logo-round-clearspace.png';
+
+export default class LocalNotification {
+    /**
+     * Create a Notification object.
+     *
+     * @param {String} title
+     * @param {String} message
+     * @param {Function} [onPress]
+     * @param {String} [icon]
+     * @param {Number} [hideAfter]
+     * @param {String} [tag]
+     */
+    constructor(title, message, onPress = () => {}, icon = EXPENSIFY_ICON_URL, hideAfter = 0, tag = '') {
+        if (!title || !message) {
+            throw new Error('LocalNotification must include title and message parameter.');
+        }
+
+        this.title = title;
+        this.message = message;
+        this.onPress = onPress;
+        this.icon = icon;
+        this.hideAfter = hideAfter;
+        this.tag = tag;
+    }
+}
diff --git a/src/libs/Notification/LocalNotification/LocalNotificationService/index.js b/src/libs/Notification/LocalNotification/LocalNotificationService/index.js
new file mode 100644
index 000000000000..913bcc498977
--- /dev/null
+++ b/src/libs/Notification/LocalNotification/LocalNotificationService/index.js
@@ -0,0 +1,72 @@
+import LocalNotification from '../LocalNotification';
+import focusApp from '../focusApp';
+
+/**
+ * Checks if the user has granted permission to show browser notifications
+ *
+ * @return {Promise}
+ */
+function canUseBrowserNotifications() {
+    return new Promise((resolve) => {
+        // They have no browser notifications so we can't use this feature
+        if (!window.Notification) {
+            return resolve(false);
+        }
+
+        // Check if they previously granted or denied us access to send a notification
+        const permissionGranted = Notification.permission === 'granted';
+
+        if (permissionGranted || Notification.permission === 'denied') {
+            return resolve(permissionGranted);
+        }
+
+        // Check their global preferences for browser notifications and ask permission if they have none
+        Notification.requestPermission()
+            .then((status) => {
+                resolve(status === 'granted');
+            });
+    });
+}
+
+/**
+ * Light abstraction around browser push notifications.
+ * Checks for permission before determining whether to send.
+ *
+ * @param {LocalNotification} notification
+ */
+function queueNotification(notification) {
+    if (!(notification instanceof LocalNotification)) {
+        throw new Error('Attempting to queue invalid LocalNotification');
+    }
+
+    canUseBrowserNotifications().then((canUseNotifications) => {
+        if (!canUseNotifications) {
+            return;
+        }
+
+        const browserNotification = new Notification(notification.title, {
+            body: notification.message,
+            icon: notification.icon,
+            tag: notification.tag,
+        });
+
+        // If we pass in a delay param greater than 0 the notification
+        // will auto-close after the specified time.
+        if (notification.hideAfter > 0) {
+            setTimeout(browserNotification.close.bind(browserNotification), notification.hideAfter);
+        }
+
+        browserNotification.onclick = (event) => {
+            event.preventDefault();
+            notification.onPress();
+            window.parent.focus();
+            window.focus();
+            focusApp();
+            browserNotification.close();
+        };
+    });
+}
+
+export default {
+    queueNotification,
+};
diff --git a/src/libs/Notification/LocalNotification/LocalNotificationService/index.native.js b/src/libs/Notification/LocalNotification/LocalNotificationService/index.native.js
new file mode 100644
index 000000000000..622910972b93
--- /dev/null
+++ b/src/libs/Notification/LocalNotification/LocalNotificationService/index.native.js
@@ -0,0 +1,107 @@
+import PushNotification from 'react-native-push-notification';
+import LocalNotification from '../LocalNotification';
+
+/*
+ * Note: react-native-push-notification uses a single global event handler for `onNotification`.
+ * So in order to provide an API similar to that of BrowserNotifications,
+ * where we can simply pass a payload and an `onPress` callback, we need to process each notification by:
+ *
+ *     1. Setting the global `onNotification` event handler to be the `onPress` callback for the given notification.
+ *     2. Triggering the local push notification.
+ *     3. Resetting the global `onNotification` event handler.
+ *
+ * That's why we need to process notifications in a queue – otherwise we could produce the following race condition:
+ *
+ *     1. A notification + callback is dispatched (call it X)
+ *     2. We set the global `onNotification` event handler to be X.onPress
+ *     3. Another notification + callback is dispatched (call it Y)
+ *     4. We set the global `onNotification` event handler to be Y.onPress
+ *     5. X.notification is displayed.
+ *     6. The user taps X.notification, and Y.onPress is executed. 😵
+ */
+
+const notificationQueue = [];
+let currentlyProcessingNotification = null;
+let onNotification = () => {};
+let channelInitialized = false;
+
+PushNotification.configure({
+    onNotification: e => onNotification(e),
+});
+
+/**
+ * Get the local notification channel (required for Android)
+ *
+ * @returns {String} – The channel ID
+ * @throws {Error} – If the channel could not be initialized.
+ */
+function getChannel() {
+    const CHANNEL_ID = 'local_push_notification';
+    if (channelInitialized) {
+        return CHANNEL_ID;
+    }
+
+    PushNotification.createChannel(
+        {
+            channelId: CHANNEL_ID,
+            channelName: CHANNEL_ID,
+        },
+        (created) => {
+            if (created) {
+                channelInitialized = true;
+                console.debug(`[LOCAL_NOTIFICATION] Local notification channel ${CHANNEL_ID} initialized`);
+                return CHANNEL_ID;
+            }
+
+            // Channel not initialized
+            throw new Error('Local notification channel not initialized');
+        },
+    );
+}
+
+/**
+ * Process the notification queue recursively.
+ *
+ * @throws {Error}
+ */
+function processQueue() {
+    currentlyProcessingNotification = notificationQueue.shift();
+    if (currentlyProcessingNotification) {
+        // Bind notification event handler
+        onNotification = currentlyProcessingNotification.onPress;
+
+        // Trigger local push notification
+        PushNotification.localNotification({
+            channelId: getChannel(),
+            title: currentlyProcessingNotification.title,
+            message: currentlyProcessingNotification.message,
+        });
+
+        // Continue to process notification queue
+        processQueue();
+    }
+}
+
+/**
+ * Add a new notification to the queue and start processing the queue if necessary.
+ *
+ * @param {LocalNotification} notification
+ * @throws {Error}
+ */
+function queueNotification(notification) {
+    if (!(notification instanceof LocalNotification)) {
+        throw new Error('Attempting to queue invalid LocalNotification');
+    }
+
+    // Add notification to the queue
+    notificationQueue.push(notification);
+
+    // Begin processing the queue if it is not already processing
+    if (!currentlyProcessingNotification) {
+        processQueue();
+    }
+}
+
+export default {
+    queueNotification,
+};
diff --git a/src/libs/Notification/LocalNotification/NotificationGenerator.js b/src/libs/Notification/LocalNotification/NotificationGenerator.js
new file mode 100644
index 000000000000..2302f5380fd0
--- /dev/null
+++ b/src/libs/Notification/LocalNotification/NotificationGenerator.js
@@ -0,0 +1,42 @@
+import Onyx from 'react-native-onyx';
+import Str from 'expensify-common/lib/str';
+import LocalNotification from './LocalNotification';
+import ONYXKEYS from '../../../ONYXKEYS';
+
+/**
+ * Process a reportAction to get a notification payload.
+ *
+ * @param {Object} reportAction
+ * @param {Function} onPress
+ * @returns {LocalNotification}
+ */
+function getReportCommentNotificationPayload(reportAction, onPress) {
+    const {person, message} = reportAction;
+    const plainTextPerson = Str.htmlDecode(person.map(f => f.text).join());
+
+    // Specifically target the comment part of the message
+    const plainTextMessage = Str.htmlDecode((message.find(f => f.type === 'COMMENT') || {}).text);
+
+    return new LocalNotification(`New message from ${plainTextPerson}`, plainTextMessage, onPress);
+}
+
+/**
+ * Generate the update available notification.
+ *
+ * @returns {LocalNotification}
+ */
+function getUpdateAvailableNotification() {
+    return new LocalNotification(
+        'Update available',
+        'A new version of Expensify.cash is available!',
+        0,
+        () => {
+            Onyx.merge(ONYXKEYS.UPDATE_AVAILABLE, true);
+        },
+    );
+}
+
+export default {
+    getReportCommentNotificationPayload,
+    getUpdateAvailableNotification,
+};
diff --git a/src/libs/Notification/LocalNotification/common.js b/src/libs/Notification/LocalNotification/common.js
new file mode 100644
index 000000000000..f63a026bdc0c
--- /dev/null
+++ b/src/libs/Notification/LocalNotification/common.js
@@ -0,0 +1,19 @@
+import LocalNotificationService from './LocalNotificationService';
+import NotificationGenerator from './NotificationGenerator';
+
+/**
+ * Create a report comment notification
+ *
+ * @param {Object} params
+ * @param {Object} params.reportAction
+ * @param {Function} params.onPress
+ * @throws {Error}
+ */
+function showCommentNotification({reportAction, onPress}) {
+    const commentNotification = NotificationGenerator.getReportCommentNotificationPayload(reportAction, onPress);
+    LocalNotificationService.queueNotification(commentNotification);
+}
+
+export default {
+    showCommentNotification: () => {},
+};
diff --git a/src/libs/Notification/LocalNotification/index.js b/src/libs/Notification/LocalNotification/index.js
index 9564b0ef7f26..eb602bd5be84 100644
--- a/src/libs/Notification/LocalNotification/index.js
+++ b/src/libs/Notification/LocalNotification/index.js
@@ -1,14 +1,16 @@
-import BrowserNotifications from './BrowserNotifications';
-
-function showCommentNotification({reportAction, onClick}) {
-    BrowserNotifications.pushReportCommentNotification({reportAction, onClick});
-}
+import LocalNotificationService from './LocalNotificationService';
+import NotificationGenerator from './NotificationGenerator';
+import commonNotifications from './common';
 
+/**
+ * Send an update available notification.
+ */
 function showUpdateAvailableNotification() {
-    BrowserNotifications.pushUpdateAvailableNotification();
+    const updateAvailableNotification = NotificationGenerator.getUpdateAvailableNotification();
+    LocalNotificationService.queueNotification(updateAvailableNotification);
 }
 
 export default {
-    showCommentNotification,
+    ...commonNotifications,
     showUpdateAvailableNotification,
 };
diff --git a/src/libs/Notification/LocalNotification/index.native.js b/src/libs/Notification/LocalNotification/index.native.js
index bbc4f48744b6..76fc702351ea 100644
--- a/src/libs/Notification/LocalNotification/index.native.js
+++ b/src/libs/Notification/LocalNotification/index.native.js
@@ -1,5 +1,8 @@
-// Local Notifications are not currently supported on mobile so we'll just noop here.
+import commonNotifications from './common';
+
 export default {
-    showCommentNotification: () => {},
+    ...commonNotifications,
+
+    // This notification is unused on iOS/Android
     showUpdateAvailableNotification: () => {},
 };
diff --git a/src/libs/Notification/PushNotification/index.native.js b/src/libs/Notification/PushNotification/index.native.js
index 3009a586c960..c78dc7435451 100644
--- a/src/libs/Notification/PushNotification/index.native.js
+++ b/src/libs/Notification/PushNotification/index.native.js
@@ -49,34 +49,16 @@ function pushNotificationEventCallback(eventType, notification) {
 }
 
 /**
- * Register this device for push notifications for the given accountID.
- *
- * @param {String|Number} accountID
+ * Register push notification callbacks. This is separate from namedUser registration because it needs to be executed
+ * from a headless JS process, outside of any react lifecycle.
  */
-function register(accountID) {
-    if (UrbanAirship.getNamedUser() === accountID.toString()) {
-        // No need to register again for this accountID.
-        return;
-    }
-
-    // Get permissions to display push notifications (prompts user on iOS, but not Android)
-    UrbanAirship.enableUserPushNotifications()
-        .then((isEnabled) => {
-            if (!isEnabled) {
-                console.debug('[PUSH_NOTIFICATIONS] User has disabled visible push notifications for this app.');
-            }
-        });
-
-    // Register this device as a named user in AirshipAPI.
-    // Regardless of the user's opt-in status, we still want to receive silent push notifications.
-    console.debug(`[PUSH_NOTIFICATIONS] Subscribing to notifications for account ID ${accountID}`);
-    UrbanAirship.setNamedUser(accountID.toString());
-
+function init() {
     // Setup event listeners
     UrbanAirship.addListener(EventType.PushReceived, (notification) => {
         // If a push notification is received while the app is in foreground,
-        // we'll assume pusher is connected so we'll ignore it and not write the same data twice.
+        // we'll assume pusher is connected so we'll ignore is and not fetch the same data twice.
         if (AppState.currentState === 'active') {
+            // eslint-disable-next-line max-len
             console.debug('[PUSH_NOTIFICATION] Push received while app is in foreground, not executing any callback.');
             return;
         }
@@ -91,6 +73,32 @@ function register(accountID) {
     });
 }
 
+/**
+ * Register this device for push notifications for the given accountID.
+ *
+ * @param {String|Number} accountID
+ */
+function register(accountID) {
+    Promise.all([
+        UrbanAirship.getNamedUser(),
+        UrbanAirship.enableUserPushNotifications(),
+    ])
+        .then(([namedUser, arePushNotificationsEnabled]) => {
+            if (!arePushNotificationsEnabled) {
+                console.debug('[PUSH_NOTIFICATIONS] User has disabled visible push notifications for this app.');
+            }
+
+            if (namedUser === accountID.toString()) {
+                console.debug('[PUSH_NOTIFICATIONS] This user is already registered for push notifications.');
+            } else {
+                // Register this device as a named user in AirshipAPI.
+                // Regardless of the user's opt-in status, we still want to receive silent push notifications.
+                console.debug(`[PUSH_NOTIFICATIONS] Subscribing to notifications for account ID ${accountID}`);
+                UrbanAirship.setNamedUser(accountID.toString());
+            }
+        });
+}
+
 /**
  * Deregister this device from push notifications.
  */
@@ -142,6 +150,7 @@ function onSelected(notificationType, callback) {
 }
 
 export default {
+    init,
     register,
     deregister,
     onReceived,
diff --git a/src/libs/Visibility/index.native.js b/src/libs/Visibility/index.native.js
index ba878d4ef7d0..08eaa375cdce 100644
--- a/src/libs/Visibility/index.native.js
+++ b/src/libs/Visibility/index.native.js
@@ -1,10 +1,11 @@
-// Mobile apps do not require this check for visibility as
-// they do not use the Notification lib.
+import {AppState} from 'react-native';
 
 /**
  * @return {Boolean}
  */
-const isVisible = () => true;
+function isVisible() {
+    return AppState.currentState === 'active';
+}
 
 export default {
     isVisible,
diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js
index 9ebc42db9629..35904c5d2926 100644
--- a/src/libs/actions/Report.js
+++ b/src/libs/actions/Report.js
@@ -514,9 +514,13 @@ function updateReportActionMessage(reportID, sequenceNumber, message) {
  *
  * @param {Number} reportID
  * @param {Object} reportAction
- * @param {String} notificationPreference On what cadence the user would like to be notified
+ * @param {String} [notificationPreference] On what cadence the user would like to be notified
  */
-function updateReportWithNewAction(reportID, reportAction, notificationPreference) {
+function updateReportWithNewAction(
+    reportID,
+    reportAction,
+    notificationPreference = CONST.NOTIFICATION_PREFERENCE.ALWAYS,
+) {
     const newMaxSequenceNumber = reportAction.sequenceNumber;
     const isFromCurrentUser = reportAction.actorAccountID === currentUserAccountID;
     const initialLastReadSequenceNumber = lastReadSequenceNumbers[reportID] || 0;
@@ -617,7 +621,7 @@ function updateReportWithNewAction(reportID, reportAction, notificationPreferenc
     console.debug('[LOCAL_NOTIFICATION] Creating notification');
     LocalNotification.showCommentNotification({
         reportAction,
-        onClick: () => {
+        onPress: () => {
             // Navigate to this report onClick
             Navigation.navigate(ROUTES.getReportRoute(reportID));
         },
@@ -715,9 +719,14 @@ function subscribeToUserEvents() {
                 {error, pusherChannelName, eventName: Pusher.TYPE.REPORT_TOGGLE_PINNED},
             );
         });
+}
 
+/**
+ * Setup reportComment push notification callbacks.
+ */
+function subscribeToReportCommentPushNotifications() {
     PushNotification.onReceived(PushNotification.TYPE.REPORT_COMMENT, ({reportID, reportAction}) => {
-        Log.info('[Report] Handled event sent by Airship', true, {reportID});
+        Log.info('[RORY_DEBUG][Report] Handled event sent by Airship', true, {reportID});
         updateReportWithNewAction(reportID, reportAction);
     });
 
@@ -1293,6 +1302,7 @@ export {
     setNewMarkerPosition,
     subscribeToReportTypingEvents,
     subscribeToUserEvents,
+    subscribeToReportCommentPushNotifications,
     unsubscribeFromReportChannel,
     saveReportComment,
     broadcastUserIsTyping,
diff --git a/src/pages/ReportDetailsPage.js b/src/pages/ReportDetailsPage.js
index 01c7ff98d9fe..16d5fefec4e9 100644
--- a/src/pages/ReportDetailsPage.js
+++ b/src/pages/ReportDetailsPage.js
@@ -21,6 +21,7 @@ import {updateNotificationPreference} from '../libs/actions/Report';
 import {Users} from '../components/Icon/Expensicons';
 import ROUTES from '../ROUTES';
 import MenuItem from '../components/MenuItem';
+import CONST from '../CONST';
 
 const propTypes = {
     ...withLocalizePropTypes,
@@ -72,16 +73,16 @@ class ReportDetailsPage extends Component {
 
         this.notificationPreferencesOptions = {
             default: {
-                value: 'always',
+                value: CONST.NOTIFICATION_PREFERENCE.ALWAYS,
                 label: props.translate('reportDetailsPage.always'),
 
             },
             daily: {
-                value: 'daily',
+                value: CONST.NOTIFICATION_PREFERENCE.DAILY,
                 label: props.translate('reportDetailsPage.daily'),
             },
             mute: {
-                value: 'mute',
+                value: CONST.NOTIFICATION_PREFERENCE.MUTE,
                 label: props.translate('reportDetailsPage.mute'),
             },
         };
diff --git a/src/setup/index.desktop.js b/src/setup/index.desktop.js
deleted file mode 100644
index 67c07723fd64..000000000000
--- a/src/setup/index.desktop.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import {AppRegistry} from 'react-native';
-import {ipcRenderer} from 'electron';
-import Config from '../CONFIG';
-import LocalNotification from '../libs/Notification/LocalNotification';
-import DateUtils from '../libs/DateUtils';
-
-
-export default function () {
-    AppRegistry.runApplication(Config.APP_NAME, {
-        rootTag: document.getElementById('root'),
-    });
-
-    ipcRenderer.on('update-downloaded', () => {
-        LocalNotification.showUpdateAvailableNotification();
-    });
-
-    // Start current date updater
-    DateUtils.startCurrentDateUpdater();
-}
diff --git a/src/setup/index.native.js b/src/setup/index.native.js
deleted file mode 100644
index 20469e3101ec..000000000000
--- a/src/setup/index.native.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// No additional setup required for native platforms
-export default function () {
-    return null;
-}
diff --git a/src/setup/index.website.js b/src/setup/index.website.js
deleted file mode 100644
index a5c603188451..000000000000
--- a/src/setup/index.website.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import {AppRegistry} from 'react-native';
-import checkForUpdates from '../libs/checkForUpdates';
-import Config from '../CONFIG';
-import HttpUtils from '../libs/HttpUtils';
-import DateUtils from '../libs/DateUtils';
-import {version as currentVersion} from '../../package.json';
-import Visibility from '../libs/Visibility';
-
-/**
- * Download the latest app version from the server, and if it is different than the current one,
- * then refresh. If the page is visibile, prompt the user to refresh.
- *
- */
-function webUpdate() {
-    HttpUtils.download('version.json')
-        .then(({version}) => {
-            if (version !== currentVersion) {
-                if (!Visibility.isVisible()) {
-                    // Page is hidden, refresh immediately
-                    window.location.reload(true);
-                    return;
-                }
-
-                // Prompt user to refresh the page
-                if (window.confirm('Refresh the page to get the latest updates!')) {
-                    window.location.reload(true);
-                }
-            }
-        });
-}
-
-/**
- * Create an object whose shape reflects the callbacks used in checkForUpdates.
- *
- * @returns {Object}
- */
-const webUpdater = () => ({
-    init: () => {
-        // We want to check for updates and refresh the page if necessary when the app is backgrounded.
-        // That way, it will auto-update silently when they minimize the page,
-        // and we don't bug the user any more than necessary :)
-        window.addEventListener('visibilitychange', () => {
-            if (!Visibility.isVisible()) {
-                webUpdate();
-            }
-        });
-    },
-    update: () => webUpdate(),
-});
-
-export default function () {
-    AppRegistry.runApplication(Config.APP_NAME, {
-        rootTag: document.getElementById('root'),
-    });
-
-    // When app loads, get current version (production only)
-    if (Config.IS_IN_PRODUCTION) {
-        checkForUpdates(webUpdater());
-    }
-
-    // Start current date updater
-    DateUtils.startCurrentDateUpdater();
-}
