From frontend-tools
Firestore data modeling best practices including subcollections, document structure, and atomic operations. PROACTIVELY activate for: (1) designing Firestore collection structures, (2) choosing between subcollections vs root collections, (3) implementing transactions vs batched writes. Triggers: "subcollection", "data model", "firestore"
How this skill is triggered — by the user, by Claude, or both
Slash command
/frontend-tools:firestore-data-modeling-patternsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Firestore is a NoSQL document database that requires careful modeling to optimize for query patterns, scalability, and cost. This skill provides patterns for structuring data effectively.
Firestore is a NoSQL document database that requires careful modeling to optimize for query patterns, scalability, and cost. This skill provides patterns for structuring data effectively.
Pattern: users/{userId}/orders/{orderId}
Use When:
Example:
// User's private sessions (accessed only via user)
users/{userId}/sessions/{sessionId}
// User's notification preferences
users/{userId}/settings/notifications
Critical Limitation: Deleting a parent document does NOT delete subcollections. You must implement cleanup logic (e.g., Cloud Function).
Pattern: Separate users and posts collections with reference fields
Use When:
Example:
// posts collection
{
id: "post1",
authorId: "user123", // Reference to users collection
title: "...",
createdAt: Timestamp
}
// Query all posts by a user
postsRef.where('authorId', '==', 'user123').get()
// Query all posts globally
postsRef.orderBy('createdAt', 'desc').limit(10).get()
Decision Matrix:
| Criterion | Subcollection | Root Collection |
|---|---|---|
| Query across parents | Requires Collection Group Query | Simple query |
| Deletion cascade | Manual cleanup needed | Independent lifecycle |
| Document limit (1MB) | Spreads data | Risk if embedding arrays |
| Semantic hierarchy | Clear parent-child | Relies on references |
Embed When:
// User profile with embedded address
{
id: "user1",
name: "Alice",
address: {
street: "123 Main St",
city: "NYC",
zip: "10001"
}
}
Reference When:
// Post references author
{
id: "post1",
title: "My Post",
authorId: "user1", // Reference
categoryIds: ["cat1", "cat2"] // Many-to-many
}
Use When: Write depends on current document state
Example: Increment a counter
import { runTransaction } from 'firebase/firestore';
await runTransaction(db, async (transaction) => {
const postRef = doc(db, 'posts', 'post1');
const postDoc = await transaction.get(postRef);
if (!postDoc.exists()) {
throw new Error('Post does not exist');
}
const newViewCount = postDoc.data().viewCount + 1;
transaction.update(postRef, { viewCount: newViewCount });
});
Characteristics:
Use When: Multiple independent write operations need atomicity
Example: Create user + settings document
import { writeBatch } from 'firebase/firestore';
const batch = writeBatch(db);
const userRef = doc(db, 'users', 'user1');
batch.set(userRef, {
name: 'Alice',
email: '[email protected]',
createdAt: serverTimestamp(),
});
const settingsRef = doc(db, 'users', 'user1', 'settings', 'notifications');
batch.set(settingsRef, {
emailNotifications: true,
pushNotifications: false,
});
await batch.commit(); // All succeed or all fail
Characteristics:
Decision Rule: Default to batched writes (simpler, faster). Use transactions only when reads are required.
Do:
Don't:
Related Skills: zod-firestore-type-safety, firebase-nextjs-integration-strategies
npx claudepluginhub agentient/vibekit --plugin frontend-toolsManages Firestore CRUD, queries, batch writes, indexes, security rules, and migrations. Use for safe production document operations, troubleshooting, and emulator validation.
Performs CRUD operations on Firestore documents with typed data, collection hierarchy exploration, and structured querying.
Manages Cloud Firestore databases including provisioning, security rules, data modeling, SDK queries, indexes, and advanced full-text search with relational joins.