# Firebase Firestore Setup Guide This document explains how to set up and use Firebase Firestore in the grateful-journal project. ## Prerequisites - Firebase project created at [console.firebase.google.com](https://console.firebase.google.com) - Node.js and npm installed ## Installation Firebase is already installed in this project. To verify, check the `package.json`: ```json { "dependencies": { "firebase": "^12.9.0", ... } } ``` ## Configuration ### 1. Set Environment Variables Copy the existing `.env.example` to `.env`: ```bash cp .env.example .env ``` ### 2. Add Firebase Project Credentials 1. Go to [Firebase Console](https://console.firebase.google.com) 2. Select your project 3. Go to **Project Settings** (gear icon) 4. Under "Your apps", find your web app 5. Copy the Firebase config object 6. Fill in the following variables in `.env`: ```env VITE_FIREBASE_API_KEY=your-api-key VITE_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com VITE_FIREBASE_DATABASE_URL=https://your-project.firebaseio.com VITE_FIREBASE_PROJECT_ID=your-project-id VITE_FIREBASE_STORAGE_BUCKET=your-project.appspot.com VITE_FIREBASE_MESSAGING_SENDER_ID=your-sender-id VITE_FIREBASE_APP_ID=your-app-id ``` ### 3. Enable Firestore in Firebase Console 1. In Firebase Console, go to **Firestore Database** 2. Click **Create Database** 3. Choose **Start in test mode** (for development) or set up security rules 4. Select your region 5. Click **Create** ## Project Structure ``` src/lib/ ├── firebase.ts # Main Firebase initialization ├── firestoreService.ts # Generic Firestore CRUD operations └── firestoreConfig.ts # Collection names and data interfaces ``` ## Usage ### Import the Firestore instance ```typescript import { db } from "@/lib/firebase"; ``` ### Use the Firestore service The `firestoreService.ts` file provides generic CRUD operations: ```typescript import { setDocument, getDocument, getDocuments, queryDocuments, updateDocument, deleteDocument, } from '@/lib/firestoreService' import { COLLECTIONS, JournalEntry } from '@/lib/firestoreConfig' // Create or update a journal entry await setDocument(COLLECTIONS.ENTRIES, entryId, { title: 'Today's thoughts', content: 'I am grateful for...', mood: 'grateful', userId: userId, createdAt: Date.now(), updatedAt: Date.now(), }) // Get a single entry const entry = await getDocument(COLLECTIONS.ENTRIES, entryId) // Get all entries const entries = await getDocuments(COLLECTIONS.ENTRIES) // Query entries with conditions import { where, orderBy } from 'firebase/firestore' const userEntries = await queryDocuments(COLLECTIONS.ENTRIES, [ where('userId', '==', userId), orderBy('createdAt', 'desc'), ]) // Update an entry await updateDocument(COLLECTIONS.ENTRIES, entryId, { updatedAt: Date.now(), }) // Delete an entry await deleteDocument(COLLECTIONS.ENTRIES, entryId) ``` ### Batch Operations ```typescript import { createWriteBatch, commitBatch } from "@/lib/firestoreService"; const batch = createWriteBatch(); // Add operations to batch batch.set(doc(db, COLLECTIONS.ENTRIES, entryId1), entryData1); batch.update(doc(db, COLLECTIONS.ENTRIES, entryId2), { mood: "happy" }); batch.delete(doc(db, COLLECTIONS.ENTRIES, entryId3)); // Commit all at once await commitBatch(batch); ``` ## Firestore Collections Schema ### users Document ID: User's auth UID ```typescript { email: string displayName?: string photoURL?: string createdAt: number (timestamp) updatedAt: number (timestamp) theme?: 'light' | 'dark' } ``` ### entries Document ID: Auto-generated or custom ID ```typescript { userId: string (reference to user) title: string content: string mood?: 'happy' | 'sad' | 'neutral' | 'anxious' | 'grateful' tags?: string[] isPublic?: boolean createdAt: number (timestamp) updatedAt: number (timestamp) } ``` ### settings Document ID: User's auth UID ```typescript { userId: string notifications?: boolean emailNotifications?: boolean theme?: 'light' | 'dark' | 'system' language?: string updatedAt: number (timestamp) } ``` ### tags Document ID: Auto-generated or custom ID ```typescript { userId: string name: string color?: string createdAt: number (timestamp) updatedAt: number (timestamp) } ``` ## Security Rules (Production) For production, update Firestore security rules in the Firebase Console: ```firestore-rules rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // Users can only read/write their own user document match /users/{userId} { allow read, write: if request.auth.uid == userId; } // Users can only read/write their own entries match /entries/{document=**} { allow read, write: if request.auth.uid == resource.data.userId; allow create: if request.auth.uid == request.resource.data.userId; } // Users can only read/write their own settings match /settings/{userId} { allow read, write: if request.auth.uid == userId; } // Users can only read/write their own tags match /tags/{document=**} { allow read, write: if request.auth.uid == resource.data.userId; allow create: if request.auth.uid == request.resource.data.userId; } } } ``` ## Local Emulator (Optional) To test locally without hitting your Firebase backend: ### 1. Install Firebase CLI ```bash npm install -g firebase-tools ``` ### 2. Initialize Firebase Emulator ```bash firebase init emulators ``` Select Firestore and Authentication emulators. ### 3. Start the Emulator ```bash firebase emulators:start ``` ### 4. Enable Emulator in Your App (Optional) Update `.env`: ```env VITE_FIREBASE_EMULATOR_ENABLED=true VITE_FIRESTORE_EMULATOR_HOST=localhost:8080 ``` The emulator connection is already commented in `src/lib/firebase.ts` - uncomment it when needed. ## Troubleshooting ### Permission Denied Error - Check your Firestore security rules in Firebase Console - Ensure your `.env` variables are correct - Make sure you're authenticated before writing to Firestore ### Document Not Found - Verify the collection name and document ID - Check if the document exists in Firestore Console - Ensure the user has read permissions ### Emulator Not Connecting - Ensure Firebase emulator is running: `firebase emulators:start` - Check that the emulator host matches your `.env` configuration - Verify port 8080 is available ## Resources - [Firebase Firestore Documentation](https://firebase.google.com/docs/firestore) - [Firestore Best Practices](https://firebase.google.com/docs/firestore/best-practices) - [Firebase Security Rules](https://firebase.google.com/docs/firestore/security/start)