All skills
firebase avatar

/firebase-firestore

@cad5019 official
by firebasefirebase/agent-skills461 stars
102

Sets up, manages, queries, and configures Cloud Firestore databases (Standard/Enterprise edition), including data modeling, security rules, indexes, and SDK integrations (Web, Python, iOS, Android, Flutter). Use when creating/listing Firestore databases, defining data models/indexes, writing SDK queries, or integrating Firestore SDKs. For authoring or modifying Firestore Security Rules (firestore.rules), delegate to the firestore-rules-author subagent if subagent delegation is available, or use firestore-rules-creation otherwise. Don't use for Firebase Hosting, Data Connect, Auth, Storage/GCS, Crashlytics, Functions, or BigQuery.

Use this Skill: https://skilld.dev/gh/firebase/agent-skills/firebase-firestore

This session only. Nothing lands on disk.

referencesenterpriseios_setup.md

≈1.5k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Firestore Enterprise Native Mode on iOS

This guide walks you through using the Cloud Firestore SDK in your iOS app using Swift.

⛔️ CRITICAL RULE: NO FirebaseFirestoreSwift ⛔️

UNDER NO CIRCUMSTANCES should you import, link against, or configure a project to use FirebaseFirestoreSwift.

As of Firebase SDK v11+, all Swift-specific features (including @DocumentID, @ServerTimestamp, and Codable support) have been fully merged into the main FirebaseFirestore module.

  • NEVER add .external(name: "FirebaseFirestoreSwift") or similar to SPM or Xcode configurations.
  • NEVER write import FirebaseFirestoreSwift in any Swift file.
  • ONLY use import FirebaseFirestore.

This is a zero-tolerance constraint. Using FirebaseFirestoreSwift is fundamentally incorrect and unacceptable.

⛔️ CRITICAL RULE: NO INLINE INITIALIZATION ⛔️

NEVER write let db = Firestore.firestore() or Firestore.firestore(database:) as an inline class or struct property if there is ANY chance the object is instantiated before FirebaseApp.configure() executes in the app root.

  • FATAL CRASH: @Observable class DataManager { let db = Firestore.firestore() } initialized as a @State in the App root.
  • SAFE PATTERN: Initialize Firestore.firestore() lazily (lazy var db = Firestore.firestore()) OR explicitly initialize the manager after FirebaseApp.configure() finishes.

1. Import and Initialize

Ensure you have installed the FirebaseFirestore SDK. Use the xcode-project-setup skill to automate adding the SPM dependency to the Xcode project.

import FirebaseFirestore

Initialize an instance of Cloud Firestore. CRITICAL: Enterprise databases require a custom database ID and cannot use the (default) instance.

// Replace "your-enterprise-database-id" with your actual database ID
let db = Firestore.firestore(database: "your-enterprise-database-id")

2. Type-Safe Data Models (Codable)

To leverage modern Swift data modeling, define your data as Codable structs. The main FirebaseFirestore module automatically supports mapping these types.

struct User: Codable {
    @DocumentID var id: String?
    var firstName: String
    var lastName: String
    var born: Int
}

3. Basic CRUD Operations

The operations are identical to standard Firestore, but ensure you use the db instance initialized with your Enterprise database ID.

Writing Data (Modern Concurrency & Codable)

let user = User(firstName: "Ada", lastName: "Lovelace", born: 1815)

do {
    // Add a new document with a generated ID using Codable
    let ref = try db.collection("users").addDocument(from: user)
    print("Document added with ID: \(ref.documentID)")
} catch {
    print("Error adding document: \(error)")
}

Reading Data (Modern Concurrency & Codable)

do {
    let querySnapshot = try await db.collection("users").getDocuments()
    
    // Map documents to the User struct automatically
    let users = querySnapshot.documents.compactMap { document in
        try? document.data(as: User.self)
    }
    
    for user in users {
        print("Found user: \(user.firstName) \(user.lastName)")
    }
} catch {
    print("Error getting documents: \(error)")
}

4. Pipeline Queries

Firestore Enterprise supports Pipeline operations for complex queries.

Initialization

let pipeline = db.pipeline()

Examples

// Return all documents across all collections in the database
let results = try await db.pipeline().database().execute()

// Filtered query
let results = try await db.pipeline()
    .collection("cities")
    .where(Field("name").equal(Constant("Toronto")))
    .execute()

// Compound query
let results = try await db.pipeline()
    .collection("books")
    .where(Field("rating").equal(5) && Field("published").lessThan(1900))
    .execute()

5. Realtime Listeners in SwiftUI (Lifecycle Best Practices)

When implementing Firestore realtime listeners (addSnapshotListener) within a SwiftUI application, you MUST tie the listener lifecycle to the view's identity using .task(id:), NOT .onDisappear.

⛔️ UNSAFE PATTERN (.onDisappear)

Presenting a .sheet or .fullScreenCover can trigger the underlying view's onDisappear method. If you stop your listener here, the feed will stop updating while the sheet is open, and won't resume when it's dismissed.

✅ SAFE PATTERN (.task with deinit)

Because addSnapshotListener is a synchronous call, placing it inside a .task means the task completes immediately. This breaks SwiftUI's automatic cancellation mechanism.

To safely manage traditional Firebase listeners in SwiftUI, you must use deinit to handle memory cleanup when the view is destroyed, and .task(id:) to handle data identity changes while the view is active.

import SwiftUI
import FirebaseFirestore

@MainActor
@Observable 
final class DataManager {
    private var listenerHandle: ListenerRegistration?
    var data: [String] = []
    
    func startListening(for userId: String) {
        // 1. Clean up any existing listener to prevent duplicates if the ID changes
        stopListening()
        
        // 2. Start the regular listener and capture the handle
        // Note: Using the global default instance here, make sure to use your enterprise instance if applicable
        // For enterprise, you might need to pass the db instance or use a shared manager.
        listenerHandle = Firestore.firestore(database: "your-enterprise-database-id").collection("users").document(userId).addSnapshotListener { snapshot, error in
            // Handle updates
        }
    }
    
    func stopListening() {
        listenerHandle?.remove()
        listenerHandle = nil
    }
    
    // 3. Guarantee cleanup when the View is destroyed and this object is deallocated
    isolated deinit {
        stopListening()
    }
}

Source: SKILL.md on GitHub

1 warning3d3 checks · Risk SAFE
  • Gen Agent Trust Hub3d

    The skill is generally safe, utilizing official Firebase tools and Google-hosted resources. It contains a minor vulnerability surface for indirect prompt injection by instructing the agent to read documentation from local library files. Additionally, it uses assertive language to mandate specific technical patterns.

  • Socket3d

    No alerts

  • Snyk3d

    Risk: MEDIUM · 1 issue

Signed by skilld at cad5019. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated last week
metadata
{
  "category": "Databases"
}
Other metadata
compatibility
This skill is best used with the Firebase CLI, but does not require it. Firebase CLI can be accessed through `npx -y firebase-tools@latest`.

README badge

README badge for firebase/agent-skills/firebase-firestore