Firestore, Auth & Storage
Reading & Writing Firestore
import { doc, getDoc, setDoc, onSnapshot, collection, query, where } from 'firebase/firestore';
// One-time read
const snap = await getDoc(doc(db, 'users', userId));
if (snap.exists()) console.log(snap.data());
// Realtime listener — callback fires on every subsequent change,
// no manual polling needed
const unsubscribe = onSnapshot(doc(db, 'users', userId), (snap) => {
console.log('updated:', snap.data());
});
// Query — filter/sort combos across multiple fields may need a
// composite index; Firestore's error message links directly to create it
const q = query(
collection(db, 'posts'),
where('published', '==', true),
);
// Subcollection — models one-to-many without bloating the parent doc
const commentsRef = collection(db, 'posts', postId, 'comments');Authentication
import { getAuth, signInWithEmailAndPassword, onAuthStateChanged } from 'firebase/auth';
const auth = getAuth();
await signInWithEmailAndPassword(auth, email, password);
onAuthStateChanged(auth, (user) => {
if (user) console.log('signed in:', user.uid);
});
// The signed-in user's ID token is what Security Rules and Cloud
// Functions use (request.auth.uid) to identify who's making a request.Security Rules
// firestore.rules — enforced server-side, regardless of client code
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /posts/{postId} {
allow read: if true;
allow write: if request.auth != null
&& request.auth.uid == request.resource.data.authorId
&& request.resource.data.price is number
&& request.resource.data.price > 0; // server-side validation —
} // client validation alone
} // can always be bypassed
}
// NEVER leave `allow read, write: if true;` in production — it grants
// full access to ANY client, including direct REST API calls.Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free