How the pieces connect
Firebase runs almost entirely in the browser. You call initializeApp(config) once, then getAuth(), getFirestore(), and getStorage() hand back singletons your React tree shares. The Firebase JS SDK opens a persistent WebSocket to Firestore, so onSnapshot pushes document changes straight into React state — no polling, no REST round-trips. The standard pattern is an auth context: a top-level provider subscribes with onAuthStateChanged, holds the User (or null) in state, and gates routes. Writes go directly from the client to Firestore; there is no API layer of your own. The only server-side code is Cloud Functions, deployed separately and invoked either over HTTPS (httpsCallable) or as background triggers like onDocumentWritten. Knowing what runs where matters: the config object and Firestore rules are public, so the security boundary lives in rules and Function checks, not in your bundle.