api-layer
API Layer Patterns
File Location
All API functions go in [feature]/api/:
src/
├── post/
│ └── api/
│ ├── post.ts # CRUD operations
│ └── postQueries.ts # React Query hooks
Function Structure
import { collection, addDoc, query, where, getDocs } from 'firebase/firestore';
import { db } from '@/firebase';
import type { Post } from '../model/Post';
export async function createPost(
boardId: string,
postData: Omit<Post, 'id' | 'createdAt'>,
): Promise<Post> {
const postsRef = collection(db, 'boards', boardId, 'posts');
const docRef = await addDoc(postsRef, {
...postData,
createdAt: new Date(),
});
return { ...postData, id: docRef.id, createdAt: new Date() };
}
Firestore Best Practices
Batch Writes for Related Operations
import { writeBatch, doc } from 'firebase/firestore';
const batch = writeBatch(db);
batch.set(doc(db, 'posts', postId), postData);
batch.update(doc(db, 'users', userId), { postCount: increment(1) });
await batch.commit();
Collection Paths
users/{userId}
users/{userId}/postings/{postingId}
users/{userId}/commentings/{commentingId}
boards/{boardId}/posts/{postId}
boards/{boardId}/posts/{postId}/comments/{commentId}
boards/{boardId}/posts/{postId}/comments/{commentId}/replies/{replyId}
Optimistic Updates with React Query
const mutation = useMutation({
mutationFn: createPost,
onMutate: async (newPost) => {
await queryClient.cancelQueries({ queryKey: ['posts'] });
const previous = queryClient.getQueryData(['posts']);
queryClient.setQueryData(['posts'], (old) => [...old, newPost]);
return { previous };
},
onError: (err, newPost, context) => {
queryClient.setQueryData(['posts'], context.previous);
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['posts'] });
},
});
Quick Reference
| Pattern | When |
|---|---|
addDoc |
Create with auto-ID |
setDoc |
Create/overwrite with known ID |
updateDoc |
Partial update |
writeBatch |
Multiple related writes |
| Listeners | Real-time features |
More from bumgeunsong/daily-writing-friends
firebase-functions
Use when creating or modifying Firebase Cloud Functions in /functions directory. Enforces function structure and error handling patterns.
43pr-stacking
PR stacking workflow for breaking large features into smaller, dependent PRs. Use when planning multi-step features, creating dependent branches, or rebasing stacked changes.
29commit
Use when creating git commits in this project
28refactoring
Use when user explicitly asks to refactor code, or when test coverage is requested for untested code with side effects. Enforces Functional Core Imperative Shell pattern extraction before any changes.
28code-style
Use when writing or modifying any code. Enforces naming conventions, function design, and code clarity principles.
28react-component
Use when creating or modifying React components (.tsx files). Enforces component structure, import order, and hooks patterns.
28