From firebase-development
Guides TDD workflow for adding features to existing Firebase projects: Cloud Functions, Firestore collections, API endpoints, security rules, emulator verification.
npx claudepluginhub 2389-research/claude-pluginsThis skill uses the workspace's default tool permissions.
This sub-skill guides adding new features to existing Firebase projects using TDD. It handles Cloud Functions, Firestore collections, and API endpoints.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
This sub-skill guides adding new features to existing Firebase projects using TDD. It handles Cloud Functions, Firestore collections, and API endpoints.
Key principles:
{success, message, data?} response patternDo not use for:
firebase-development:project-setupfirebase-development:debugfirebase-development:validateCreate checklist with these 12 steps:
Determine what's being added:
Examine the project to understand patterns:
ls -la functions/src/
grep -r "onRequest" functions/src/
grep "express" functions/package.json
Determine: Architecture style, auth method, security model.
Reference: docs/examples/express-function-architecture.md
Create test file before implementation:
// ABOUTME: Unit tests for [feature name] functionality
// ABOUTME: Tests [what the feature does] with various scenarios
import { describe, it, expect } from 'vitest';
import { handleYourFeature } from '../../tools/yourFeature';
describe('handleYourFeature', () => {
it('should return success when given valid input', async () => {
const result = await handleYourFeature('user-123', { name: 'test' });
expect(result.success).toBe(true);
});
it('should return error for invalid input', async () => {
const result = await handleYourFeature('user-123', { name: '' });
expect(result.success).toBe(false);
});
});
Run test to confirm it fails: npm run test
Create implementation file:
// ABOUTME: Implements [feature name] for [purpose]
// ABOUTME: Returns {success, message, data?} response
export async function handleYourFeature(
userId: string,
params: { name: string }
): Promise<{ success: boolean; message: string; data?: any }> {
if (!userId) {
return { success: false, message: 'Authentication required' };
}
if (!params.name) {
return { success: false, message: 'Invalid input: name required' };
}
// Implementation here
return { success: true, message: 'Success', data: { /* ... */ } };
}
Reference: docs/examples/express-function-architecture.md
Update firestore.rules for new collections:
Server-write-only (preferred):
match /yourCollection/{docId} {
allow read: if request.auth != null;
allow write: if false; // Only Cloud Functions
}
Client-write (if needed):
match /yourCollection/{docId} {
allow create: if request.auth != null &&
request.resource.data.userId == request.auth.uid;
allow update: if request.auth != null &&
resource.data.userId == request.auth.uid &&
request.resource.data.diff(resource.data).affectedKeys()
.hasOnly(['name', 'updatedAt']);
}
Reference: docs/examples/firestore-rules-patterns.md
Add to firestore.indexes.json for complex queries:
{
"collectionGroup": "yourCollection",
"fields": [
{"fieldPath": "userId", "order": "ASCENDING"},
{"fieldPath": "createdAt", "order": "DESCENDING"}
]
}
Skip if no complex queries (single-field indexes are automatic).
Based on project pattern:
API Keys:
app.post('/endpoint', apiKeyGuard, async (req, res) => {
const userId = req.userId!;
// ...
});
Firebase Auth:
if (!req.auth) {
res.status(401).json({ success: false, message: 'Auth required' });
return;
}
const userId = req.auth.uid;
Reference: docs/examples/api-key-authentication.md
All handlers use consistent pattern:
interface HandlerResponse {
success: boolean;
message: string;
data?: any;
}
Include validation at every layer (defense in depth).
Add to functions/src/index.ts:
Express: Add route or switch case
Domain-grouped: export * from './yourDomain';
Individual: Import and export in index.js
Verify: npm run build
Run tests: npm run test
All tests should pass. If not, fix implementation (not tests).
Create functions/src/__tests__/emulator/yourFeature.test.ts:
Test complete workflow with emulators:
Run: npm run test:emulator (with emulators running)
firebase emulators:start
open http://127.0.0.1:4000
Verify:
All handlers MUST return:
// Success
{ success: true, message: "Created", data: { id: "abc" } }
// Error
{ success: false, message: "Invalid input" }
Before marking complete:
docs/examples/express-function-architecture.mddocs/examples/api-key-authentication.mddocs/examples/firestore-rules-patterns.mddocs/examples/emulator-workflow.md