Use Cases (अपडेट: 1/6/2026)

Claude Code से Firestore Schema Design: GCP/Firebase SaaS Guide

Claude Code के साथ Firestore collections, rules, indexes और SaaS schema सुरक्षित तरीके से design करें।

Claude Code से Firestore Schema Design: GCP/Firebase SaaS Guide

Firestore design collection name से नहीं, read pattern से शुरू करें

मैं Masa हूं, claudecode-lab.com चलाता हूं।

Firestore सीखते समय मेरी पहली गलती बहुत सामान्य थी। मैंने पहले users, projects, events, subscriptions जैसी collections बना दीं। शुरुआत में schema साफ दिखा, लेकिन SaaS screens बढ़ते ही समस्या आई: user के projects, project members, recent events, trial users, billing status और admin view. Structure अच्छा दिख रहा था, पर queries product से match नहीं कर रही थीं।

Firestore relational database नहीं है जहां बाद में JOIN से सब ठीक कर देंगे। Official data model के अनुसार data documents में रहता है और documents collections में रहते हैं। Document में fields, objects और subcollections हो सकते हैं। आसान भाषा में: collection एक shelf है, document एक file है, और subcollection उस file के अंदर की छोटी folder है।

इसलिए सही क्रम है: screens, queries, schema, Security Rules, indexes. Claude Code को code generator की तरह नहीं, local design reviewer की तरह इस्तेमाल करें। उसे firestore.rules, firestore.indexes.json, TypeScript types और query functions साथ में दिखाएं ताकि वह contradictions पकड़ सके।


SaaS के लिए collections, documents और subcollections

एक छोटे B2B SaaS के लिए यह structure practical है:

users/{uid}
projects/{projectId}
projects/{projectId}/members/{uid}
projects/{projectId}/events/{eventId}
subscriptions/{uid}
billingCustomers/{uid}
PathकामTypical read
users/{uid}user profilecurrent user profile
projects/{projectId}workspace या customer projectproject detail
projects/{projectId}/members/{uid}project rolemember list और permission
projects/{projectId}/events/{eventId}activity और audit logrecent project events
subscriptions/{uid}plan और payment statusfeature gating
billingCustomers/{uid}Stripe या billing IDsserver jobs only

Subcollection तभी रखें जब वह common read को आसान बनाती हो। अगर screen हमेशा एक project के 50 recent events पढ़ती है, तो projects/{projectId}/events सही है। अगर cross-project view चाहिए, तो collection group query देख सकते हैं, लेकिन उसके साथ rules और composite index भी design करने होंगे।

Claude Code prompt:

claude -p "
B2B SaaS के Firestore design को review करें।
Collections propose करने से पहले screen-wise query inventory बनाएं।

Screens:
- current user के projects
- project detail
- project के last 50 events
- admin subscription status list
- users whose trial ends soon

हर screen के लिए where/orderBy/limit,
required Composite index और Security Rules condition बताएं।
"

User, project, event और billing schema example

यह TypeScript model Firebase Admin SDK या Cloud Functions के लिए है।

import type { Timestamp } from "firebase-admin/firestore";

export type ProjectRole = "owner" | "admin" | "member" | "viewer";
export type SubscriptionStatus =
  | "trialing"
  | "active"
  | "past_due"
  | "canceled";

export interface ProjectDoc {
  id: string;
  name: string;
  ownerUid: string;
  plan: "free" | "starter" | "pro";
  memberCount: number;
  lastEventAt: Timestamp | null;
  createdAt: Timestamp;
  updatedAt: Timestamp;
}

export interface ProjectMemberDoc {
  uid: string;
  role: ProjectRole;
  displayName: string;
  email: string;
  joinedAt: Timestamp;
}

export interface ProjectEventDoc {
  id: string;
  projectId: string;
  actorUid: string;
  actorName: string;
  type: "created" | "updated" | "commented" | "exported";
  message: string;
  createdAt: Timestamp;
}

export interface SubscriptionDoc {
  uid: string;
  status: SubscriptionStatus;
  plan: "free" | "starter" | "pro";
  trialEndsAt: Timestamp | null;
  updatedAt: Timestamp;
}

ProjectMemberDoc में displayName और email रखना intentional denormalization है। Denormalization का मतलब है display के लिए छोटे data को copy करना ताकि extra reads कम हों। Firestore में 50 members दिखाने के लिए 50 अलग users/{uid} पढ़ना महंगा हो सकता है। Name copy करने से list fast होती है; profile change पर sync करना पड़ता है।

Example 1: home dashboard के लिए per-user project reference useful है।

users/{uid}/projectRefs/{projectId}
  projectId: string
  projectName: string
  role: "owner" | "admin" | "member" | "viewer"
  lastEventAt: Timestamp | null

यह pure normalized model नहीं है, लेकिन first screen को predictable single query बना देता है।


Security Rules filter नहीं हैं

यह सबसे बड़ा trap है। Official secure query documentation साफ कहती है कि Security Rules filters नहीं हैं। Query पूरी allow होती है या पूरी reject. अगर query कोई unauthorized document return कर सकती है, तो query fail होगी।

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    match /projects/{projectId}/events/{eventId} {
      allow list: if request.auth != null
        && exists(/databases/$(database)/documents/projects/$(projectId)/members/$(request.auth.uid))
        && request.query.limit <= 50;
    }
  }
}

यह query गलत है क्योंकि इसमें limit नहीं है।

import { collection, getDocs } from "firebase/firestore";

await getDocs(collection(db, "projects", projectId, "events"));

सही query rules से match करती है।

import {
  collection,
  getDocs,
  limit,
  orderBy,
  query,
} from "firebase/firestore";

export async function listProjectEvents(projectId: string) {
  const eventsQuery = query(
    collection(db, "projects", projectId, "events"),
    orderBy("createdAt", "desc"),
    limit(50),
  );

  const snap = await getDocs(eventsQuery);
  return snap.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
}

Example 2: अगर rule सिर्फ visibility == "public" allow करती है, तो query में भी where("visibility", "==", "public") होना चाहिए। Firestore अपने आप private documents हटाकर public वाले return नहीं करता।


Composite index और collection group query

Firestore basic indexes बना देता है, लेकिन कई filters और sorting साथ हों तो composite index चाहिए। Official indexing documentation बताती है कि missing index होने पर error में create link मिल सकता है। Team project में firestore.indexes.json को Git में रखना बेहतर है।

{
  "indexes": [
    {
      "collectionGroup": "events",
      "queryScope": "COLLECTION_GROUP",
      "fields": [
        { "fieldPath": "projectId", "order": "ASCENDING" },
        { "fieldPath": "createdAt", "order": "DESCENDING" }
      ]
    },
    {
      "collectionGroup": "subscriptions",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "status", "order": "ASCENDING" },
        { "fieldPath": "trialEndsAt", "order": "ASCENDING" }
      ]
    }
  ],
  "fieldOverrides": []
}

Collection group query एक ही ID वाली सभी subcollections पर query चलाती है।

import {
  collectionGroup,
  getDocs,
  limit,
  orderBy,
  query,
  where,
} from "firebase/firestore";

export async function listRecentEventsAcrossProjects(projectId: string) {
  const eventsQuery = query(
    collectionGroup(db, "events"),
    where("projectId", "==", projectId),
    orderBy("createdAt", "desc"),
    limit(50),
  );

  const snap = await getDocs(eventsQuery);
  return snap.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
}

Rules भी उसी pattern को cover करें। Official rules structure बताती है कि match document path पर होता है, collection पर नहीं। Collection group query के लिए rules version 2 और recursive wildcard का design चाहिए।

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    function signedIn() {
      return request.auth != null;
    }

    function isProjectMember(projectId) {
      return signedIn()
        && exists(/databases/$(database)/documents/projects/$(projectId)/members/$(request.auth.uid));
    }

    match /{path=**}/events/{eventId} {
      allow list: if signedIn()
        && request.query.limit <= 50
        && resource.data.projectId is string
        && isProjectMember(resource.data.projectId);
    }
  }
}

Emulator में test करें। अगर बाद में email logs या billing logs भी events नाम से बना दिए, collection group query उन्हें भी छू सकती है। अलग access rules हों तो projectEvents और billingEvents जैसे names बेहतर हैं।


Claude Code से local design review

मैं repo में docs/firestore-schema.md, firestore.rules, firestore.indexes.json, और query functions रखकर यह prompt चलाता हूं।

claude -p "
इस Firestore design को locally review करें।
Files:
- docs/firestore-schema.md
- firestore.rules
- firestore.indexes.json
- src/lib/firestore/queries.ts

Check:
1. हर screen query schema से match करती है?
2. Security Rules को filter की तरह तो नहीं इस्तेमाल किया?
3. list queries में required where/orderBy/limit हैं?
4. Composite index missing या excessive हैं?
5. Collection group query बहुत broad है?
6. Client subscription status बदल सकता है?
7. कौन सा screen बहुत ज्यादा document reads करता है?

Problems, reasons और fixed code दें।
"

Example 3: subscription status. Client को subscriptions/{uid} लिखने की अनुमति न दें। Stripe webhook या Cloud Function server side से लिखे।

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    match /subscriptions/{uid} {
      allow get: if request.auth != null && request.auth.uid == uid;
      allow list: if false;
      allow create, update, delete: if false;
    }
  }
}

Server पर भी plan check करें। UI में button छिपाना authorization नहीं है।

import { getFirestore } from "firebase-admin/firestore";

const db = getFirestore();

export async function assertActiveSubscription(uid: string) {
  const snap = await db.collection("subscriptions").doc(uid).get();
  const data = snap.data();

  if (!data || !["trialing", "active"].includes(data.status)) {
    throw new Error("Active subscription required");
  }

  return data;
}

Masa verification note: मैंने contact management, content admin और छोटे SaaS demo में यह flow आजमाया। Collection names से शुरू करने पर बाद में rewrites आए। Query table पहले बनाकर Claude Code से rules और index review कराने पर design जल्दी साफ हुआ। सबसे common failures थे sequential document IDs, rules और queries को अलग-अलग review करना, billing status को users/{uid} में मिलाना, और हर log को events नाम देना।

GCP integration आगे बढ़ाना हो तो Claude Code x GCP Cloud Functions और Claude Code x GCP Cloud Run पढ़ें। API boundary unclear हो तो Claude Code से REST API design useful है। ClaudeCodeLab इन patterns को free PDF, learning material और consultation checklist में बदल रहा है; schema, rules और query list लेकर आएंगे तो review बहुत concrete हो जाएगा।

#claude-code #gcp #firestore #database #typescript #query-design
मुफ़्त

मुफ़्त PDF: Claude Code cheatsheet

Email डालें और commands, review habits तथा safe workflow वाली एक-page PDF पाएँ.

हम आपका data सुरक्षित रखते हैं और spam नहीं भेजते.

Masa

लेखक के बारे में

Masa

Claude Code workflow और team adoption पर काम करने वाला engineer.