> For the complete documentation index, see [llms.txt](https://lionstudios.gitbook.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lionstudios.gitbook.io/readme/features/remote-storage/firestore.md).

# Firestore

### **Introduction**

A flexible, scalable database for our games. Like realtime database, it keeps user data in sync across client apps.

### **Prerequisites**

* You must have access to Firebase console project of the game

### Create Firestore Database

1. Go to the Firestore Database on the sidebar
2. Click on “Create database”

<figure><img src="/files/eFpsk74KN7FZaVZuY6rB" alt="" width="563"><figcaption></figcaption></figure>

3. It will present a popup to select the location of the database. Keep the default values
4. Click Next

<figure><img src="/files/1bR05o647sDxIEbvDwC0" alt="" width="563"><figcaption></figcaption></figure>

5. Select “Start in production mode” and click "Create"

<figure><img src="/files/xrWd47bdaO6PTOON7GYC" alt="" width="563"><figcaption></figcaption></figure>

6. Copy-paste the code block given below into the `Rules` window of your Firestore Database.

```firestore-security-rules
rules_version = '2';
service cloud.firestore 
{
  match /databases/{database}/documents 
  {
    function signedIn() { return request.auth != null; }
  
    // Device-like IDs: 32-hex OR UUID-with-dashes OR generic 16–64 hex
    function isDeviceId(id) {
      return
        id.matches('^[0-9A-Fa-f]{32}$') ||                         // 32 hex
        id.matches('^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$') || // UUID
        id.matches('^[0-9A-Fa-f]{16,64}$');                         // other hex lengths (e.g., 16, 40, 64)
    }
       
    // /<anyCollection>/<UID or deviceId>
    match /{collectionId}/{userId} {
      allow read, write: if signedIn() && (
        request.auth.uid == userId ||      // own UID doc
        isDeviceId(userId)                 // any deviceId doc (see caveat)
      );
    }
       
    // Any depth under those docs
    match /{collectionId}/{userId}/{document=**} {
      allow read, write: if signedIn() && (
        request.auth.uid == userId ||
        isDeviceId(userId)
      );
    }
       
    // Deny everything else
    match /{document=**} {
      allow read, write: if false;
    }
  }
}
```

7. Click on `Authentication/Sign-in method` and click the "Add new provider" button. Enable the following providers:

   <figure><img src="/files/7Ww81TI3XIHSdq8IZTFR" alt=""><figcaption></figcaption></figure>

   * [**Email/Password Auth**](/readme/features/remote-storage/firestore/email-password-auth.md) — **Required**. Base authentication for Remote Storage.
   * [**Facebook Auth**](/readme/features/remote-storage/firestore/facebook-auth.md) — Optional. Enables cross-device data sync via Facebook login.

<p align="center"><br><strong>At this point, Firestore &#x26; Firebase Auth dashboard setup is complete!!</strong></p>

### Configure Firestore in Unity

1. Install the Cloud Firestore & Firebase Authentication packages from Lion Registry under My Registries→ Lion Studios - Third Party SDKs→ Cloud Firestore.

<figure><img src="/files/Uo6st1vndL25mstkuEAu" alt="" width="563"><figcaption><p>Install Firestore And Auth</p></figcaption></figure>

### Implementation

#### Merge Conflict Data

If you're using Firestore as your save data backend, pass a `MergeConflictData` object to your `RemoteStorage.Save(MergeConflictData)` calls. This data drives automatic conflict resolution when syncing data between devices.

This **MergeConflictData** object has the following fields you can set.

* **`PlayerXP`**: This is where you pass information about the players progression in the game. If you have any internal progression tracking metric then use that here.
  * **Tip:** In the case that if your game doesn't have a PlayerXP equivalent, you should pass some data variable that increases every time the save method is called.
* **`LastPurchaseUtc`**: Set this to the timestamp of the user's most recent in-app purchase. You will have to keep track of this timestamp internally.

Below is an example of how to use it:

```csharp
MergeConflictData data = new MergeConflictData();
data = RemoteStorage.CurrentMergeConflictData ?? new MergeConflictData();
data.PlayerXP += amount;
data.LastPurchaseUtc = InternalDataManager.GetLastPurchaseTime(); // Your logic here
bool synced = await RemoteStorage.Save(data);
```

If there is a conflict between two device's data, then our system chooses user data depending upon,

* Whichever device has the most recent IAP purchase time
* Higher value of playerXP
* Most recent save time (This save time is tracked internally by us)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://lionstudios.gitbook.io/readme/features/remote-storage/firestore.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
