diff --git a/firestore/.gitignore b/firestore/.gitignore
new file mode 100644
index 000000000..21fb2dcb6
--- /dev/null
+++ b/firestore/.gitignore
@@ -0,0 +1,44 @@
+testapp/**/*.dll
+testapp/**/*.pdb
+testapp/**/*.bundle
+testapp/**/*.meta
+
+testapp/Assets/Plugins
+testapp/Assets/StreamingAssets
+testapp/Assets/Editor Default Resources
+testapp/Assets/ExternalDependencyManager
+testapp/Assets/Firebase/Editor/*.xml
+testapp/Assets/Firebase/Editor/*.txt
+testapp/Assets/Firebase/Editor/*.exe
+testapp/Assets/Firebase/Editor/*.py
+testapp/Assets/Firebase/Sample/AutomatedTestRunner.cs
+testapp/Assets/Firebase/Sample/ftl_testapp_files
+testapp/Assets/Firebase/m2repository
+
+testapp/Library
+testapp/Logs
+testapp/Packages
+testapp/Temp
+testapp/UserSettings
+testapp/android_BackUpThisFolder_ButDontShipItWithYourGame
+testapp/ios
+testapp/macos.app/Contents
+testapp/obj/Debug
+testapp/Assembly-CSharp-Editor.csproj
+testapp/Assembly-CSharp-firstpass.csproj
+testapp/Assembly-CSharp.csproj
+testapp/Tests.csproj
+testapp/android.apk
+testapp/android_mapping.txt
+testapp/testapp.sln
+
+testapp/ProjectSettings/AndroidResolverDependencies.xml
+testapp/ProjectSettings/GvhProjectSettings.xml
+testapp/ProjectSettings/MemorySettings.asset
+testapp/ProjectSettings/PackageManagerSettings.asset
+testapp/ProjectSettings/PresetManager.asset
+testapp/ProjectSettings/TimelineSettings.asset
+testapp/ProjectSettings/VFXManager.asset
+testapp/ProjectSettings/VersionControlSettings.asset
+testapp/ProjectSettings/XRSettings.asset
+testapp/ProjectSettings/boot.config
diff --git a/firestore/CONTRIBUTING.md b/firestore/CONTRIBUTING.md
new file mode 100644
index 000000000..919a0c6f3
--- /dev/null
+++ b/firestore/CONTRIBUTING.md
@@ -0,0 +1,89 @@
+# Overview
+
+This describes how Firestore Unity SDK works, and how to develop and test 
+the SDK, targeting desktop/Android/iOS.
+
+# Prerequisites
+
+Building the Unity SDK requires building the underlying C++ SDK. Refer to
+[https://github.com/firebase/firebase-cpp-sdk#prerequisites][this doc] for 
+what the prerequisites are.
+
+On top of above, you also need Unity installed (obviously). If you use an
+apple silicon machine as host, be sure to install Unity for Apple Silicon,
+otherwise Unity will report missing binaries when you try to run the Testapp.
+
+# Building Firestore Unity SDK
+
+Building Firestore into Unity Packages is a very involved process, mixed with
+multiple build tools working together. Therefore, we will rely on Python scripts
+to automate the process. The scripts live under `$REPO_ROOT/scripts/build_scripts`.
+
+```zsh
+# all scripts are run from the repo root.
+
+# Building for Mac. The build tools will try to find Unity automatically
+python scripts/build_scripts/build_zips.py -platform=macos -targets=auth -targets=firestore -use_boringssl
+
+# If above does not work, try specify Unity path direcly
+python scripts/build_scripts/build_zips.py -platform=macos -unity_root=<PATH_TO_UNITY> -targets=auth -targets=firestore -use_boringssl
+
+# Building for Android
+python scripts/build_scripts/build_zips.py -platform=android -targets=auth -targets=firestore -use_boringssl
+
+# Building for iOS. Incremental build for iOS is broken, so we use clean_build here.
+python scripts/build_scripts/build_zips.py -platform=android -targets=auth -targets=firestore -use_boringssl -clean_build
+
+# Build with OPENSSL: above use boringssl by default, which could add to build time, you can
+# use a binary OPENSSL if you want to, by specifying the location with a ENV Variable.
+OPENSSL_ROOT_DIR=/opt/homebrew/opt/openssl@1.1 python scripts/build_scripts/build_zips.py -platform=macos -targets=auth -targets=firestore
+
+
+# Other supported platforms are tvos,linux,windows
+```
+
+After running above commands, some zip files for each platform are created under
+`$PLATFORM_unity` directories. Run below to put all of them into Unity packages:
+
+```zsh
+# Built Unity packages for all platforms are stored under ./package_dir
+python scripts/build_scripts/zips_to_packages.py --output package_dir
+```
+
+# Running Firestore Desktop TestApp
+
+Test app for Firestore is under `firestore/testapp`, we need to copy a 
+`google-services.json` or `GoogleServices-Info.plist` to `firestore/testapp/Assets/Firebase/Sample/Firestore`
+before we can run the test app.
+
+The testapp depends on a custom test runner, which is needs to be copied over unfortunately:
+
+```zsh
+cp ./scripts/gha/integration_testing/automated_testapp/AutomatedTestRunner.cs firestore/testapp/Assets/Firebase/Sample/
+cp -r ./scripts/gha/integration_testing/automated_testapp/ftl_testapp_files firestore/testapp/Assets/Firebase/Sample/
+```
+
+To run the test app, open `firestore/testapp` from Unity Editor, and load the Unity packages we built above.
+Then open up `firestore/testapp/Assets/Firebase/Sample/Firestore/MainSceneAutomated.unity`, you should be
+able to run this scene which in turn runs all integration tests for Firestore.
+
+# Running Firestore Android TestApp
+
+*Apple Silicon Unity user*: you need to use `IL2CPP` as scripting backend instead of `Mono` for Android, otherwise you
+cannot target for `ARM64`. To do this, you can go to 
+`Edit->Project Setting->Player->Android->Scripting Backend` and select `IL2CPP`, and also select `Arm64` as target.
+
+You also need to turn on `minification` under on the same setting page, by turning on `R8` under `publish
+settings`. Otherwise you could see build error from task `minifyDebugWithProguard`.
+
+To run the Android testapp, go to `File->Build Settings`, select `Android` then click `Switch Platform`. After
+assets are loaded, click `Build and Run`.
+
+# Running Firestore iOS TestApp
+
+Similarly for iOS, go to `File-Build Settings` and select `iOS`. After you click `Build and Run`, it will prompt
+you to select a directory to save generated code and XCode project.
+
+After the code generation is done, go under the directory, and run `pod install` to generate
+a `xcworkspace`, then open it via `XCode`. From `XCode` you should be able to sign the testapp, build and run/debug
+the app with an actual iOS device, or as an iPad App on an Apple Silicon mac.
diff --git a/firestore/testapp/Assets/Firebase/Editor/Builder.cs b/firestore/testapp/Assets/Firebase/Editor/Builder.cs
index 6a1282f9c..32fd70007 100644
--- a/firestore/testapp/Assets/Firebase/Editor/Builder.cs
+++ b/firestore/testapp/Assets/Firebase/Editor/Builder.cs
@@ -51,7 +51,7 @@ public static void BuildTvos() {
     options.locationPathName = "tvos-build";
     options.target = BuildTarget.tvOS;
     // Firebase Unity plugins don't seem to work on a simulator.
-    PlayerSettings.tvOS.sdkVersion = tvOSSdkVersion.DeviceSDK;
+    PlayerSettings.tvOS.sdkVersion = tvOSSdkVersion.Device;
 
     // AcceptExternalModificationsToPlayer corresponds to "Append" in the Unity
     // UI -- it allows doing incremental builds.
diff --git a/scripts/build_scripts/build_zips.py b/scripts/build_scripts/build_zips.py
index 1a7226f74..c2a43071c 100644
--- a/scripts/build_scripts/build_zips.py
+++ b/scripts/build_scripts/build_zips.py
@@ -466,7 +466,7 @@ def make_macos_arch(arch, cmake_args):
   build_dir = os.path.join(os.getcwd(), arch)
   cmake_args.append('-DCMAKE_OSX_ARCHITECTURES='+arch)
   subprocess.call(cmake_args, cwd=build_dir)
-  subprocess.call('make', cwd=build_dir)
+  subprocess.call(['make'], cwd=build_dir)
   subprocess.call(['cpack', '.'], cwd=build_dir)
 
 def make_macos_multi_arch_build(cmake_args):
@@ -565,7 +565,7 @@ def make_tvos_target(device, arch, cmake_args):
     os.makedirs(arch)
   build_dir = os.path.join(os.getcwd(), arch)
   subprocess.call(build_args, cwd=build_dir)
-  subprocess.call('make', cwd=build_dir)
+  subprocess.call(['make'], cwd=build_dir)
   subprocess.call(['cpack', '.'], cwd=build_dir)
 
 def make_tvos_multi_arch_build(cmake_args):
@@ -795,7 +795,7 @@ def main(argv):
       # no make command in windows. TODO make config passable
       subprocess.call("cmake --build .  --config Release")
     else:
-      subprocess.call("make")
+      subprocess.call(["make"])
 
     cmake_pack_args = [
         "cpack",
diff --git a/scripts/build_scripts/zips_to_packages.py b/scripts/build_scripts/zips_to_packages.py
new file mode 100644
index 000000000..e6520750b
--- /dev/null
+++ b/scripts/build_scripts/zips_to_packages.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+#
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Collects built zips(built by build_zips.py) under current directory
+and packages them into Unity Packages using build_packages.py.
+
+Example usage:
+  python zips_to_packages.py --ouput unity_packages
+"""
+import glob
+import os
+import shutil
+import subprocess
+import zipfile
+import tempfile
+import threading
+import sys
+
+from absl import app, flags, logging
+
+FLAGS = flags.FLAGS
+flags.DEFINE_string(
+    'output', 'unity_packages',
+    'Relative directory to save the generated unity packages')
+
+def main(argv):
+  if len(argv) > 1:
+    raise app.UsageError('Too many command-line arguments.')
+  output = FLAGS.output
+
+  if os.path.exists(output):
+    shutil.rmtree(output)
+  if not os.path.exists(output):
+    os.makedirs(output)
+  logging.info("Ready to build Unity packages to {}".format(output))
+	
+  zip_temp_dir = tempfile.mkdtemp()
+
+  try:
+    candidates = glob.glob('./*_unity/firebase_unity*.zip')
+    for candidate in candidates:
+      shutil.copy(candidate, zip_temp_dir)
+
+    if len(candidates) > 0:
+      logging.info("Found zip files:\n {}".format("\n".join(candidates)))
+      subprocess.call(["python", "scripts/build_scripts/build_package.py", 
+			  "--zip_dir", zip_temp_dir, "-output", output])
+  finally:
+    shutil.rmtree(zip_temp_dir)
+	
+if __name__ == '__main__':
+  app.run(main)