Conversation
WalkthroughDocs for Firebase setup/deployment were removed. Firebase initialization in Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor App as App Startup
participant FB as Firebase SDK
participant FS as Firestore
participant ST as Storage
participant Emu as Emulators (optional)
App->>FB: initializeApp(firebaseConfig)
FB-->>App: app
App->>FS: getFirestore(app)
App->>ST: getStorage(app)
alt NEXT_PUBLIC_USE_FIREBASE_EMULATOR == "true" && typeof window !== "undefined"
App->>Emu: connectFirestoreEmulator(host??"localhost", port??"8080")
App->>Emu: connectStorageEmulator(host??"localhost", port??"9199")
end
App-->>App: export app, db, storage
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
.gitignore (1)
14-15: LGTM on ignoring Playwright reporter outputs; confirm intended scope (root vs anywhere).Without a leading slash, these files will be ignored in any subdirectory. If you only intend to ignore files at repo root, add a leading
/.Optional diff to scope to root only:
- test-results.json - test-results.xml + /test-results.json + /test-results.xml.github/workflows/playwright.yml (1)
82-82: Fix YAML lint error: add a trailing newline at EOF.The workflow currently lacks a newline at the end of the file, tripping YAMLlint.
Apply this minimal change:
- retention-days: 30 + retention-days: 30 +
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
firestore-debug.logis excluded by!**/*.log
📒 Files selected for processing (12)
.github/workflows/playwright.yml(1 hunks).gitignore(2 hunks)DEPLOYMENT_SETUP.md(0 hunks)FIREBASE_SETUP.md(0 hunks)FUNCTIONS_DEPLOYMENT.md(0 hunks)GETTING_STARTED.md(0 hunks)lib/firebase.ts(1 hunks)lib/firestore.ts(0 hunks)lib/storage.ts(0 hunks)next.config.ts(0 hunks)test-results.json(0 hunks)test-results.xml(0 hunks)
💤 Files with no reviewable changes (9)
- test-results.json
- DEPLOYMENT_SETUP.md
- test-results.xml
- FIREBASE_SETUP.md
- next.config.ts
- GETTING_STARTED.md
- lib/storage.ts
- FUNCTIONS_DEPLOYMENT.md
- lib/firestore.ts
🧰 Additional context used
🪛 YAMLlint (1.37.1)
.github/workflows/playwright.yml
[error] 82-82: no new line character at the end of file
(new-line-at-end-of-file)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Playwright Tests
- GitHub Check: Playwright Tests
- GitHub Check: test-mobile
- GitHub Check: test (webkit)
- GitHub Check: test (firefox)
🔇 Additional comments (2)
.gitignore (1)
60-60: No-op formatting change acknowledged.Thumbs.db entry remains; added/normalized trailing newline only. All good.
lib/firebase.ts (1)
14-16: Initialize Firebase as a singleton (avoid “[DEFAULT] already exists” on HMR / SSR)Use getApps()/getApp() instead of calling initializeApp directly; mark the module client-only if it’s imported by client components or uses firebase/storage.
File: lib/firebase.ts (around lines 14–16)
-import { initializeApp, getApps, FirebaseApp } from 'firebase/app'; +import { initializeApp, getApps, getApp, FirebaseApp } from 'firebase/app';-const app = initializeApp(firebaseConfig); +const app: FirebaseApp = getApps().length ? getApp() : initializeApp(firebaseConfig);Add client-only directive when appropriate:
+'use client';Verification note: my automated scan returned no imports of lib/firebase and printing lib/firebase.ts failed in the sandbox environment — ensure no server components import lib/firebase without a top-line "use client".
| ); | ||
|
|
||
| // Initialize Storage | ||
| let storage: FirebaseStorage; | ||
| if (typeof window !== 'undefined') { | ||
| storage = getStorage(app); | ||
|
|
||
| // Connect to Storage emulator in development | ||
| if (process.env.NODE_ENV === 'development' && process.env.NEXT_PUBLIC_USE_FIREBASE_EMULATOR === 'true') { | ||
| const emulatorHost = process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_HOST || 'localhost'; | ||
| const emulatorPort = process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_STORAGE_PORT || '9199'; | ||
|
|
||
| try { | ||
| connectStorageEmulator(storage, emulatorHost, parseInt(emulatorPort)); | ||
| console.log('Connected to Storage emulator'); | ||
| } catch { | ||
| // Emulator already connected | ||
| console.log('Storage emulator already connected'); | ||
| } | ||
| } | ||
| } else { | ||
| storage = getStorage(app); | ||
| connectStorageEmulator( | ||
| storage, | ||
| process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_HOST ?? 'localhost', | ||
| parseInt(process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_STORAGE_PORT ?? '9199') | ||
| ); | ||
| } | ||
|
|
||
|
|
||
| export { app, db, storage }; | ||
| export default app; |
There was a problem hiding this comment.
Harden emulator config: strict check, prod guard, safe port parsing, and client-only storage.
- Use
===and guard against accidental prod usage. - Handle empty strings (env present but empty) and specify radix for
parseInt. - Only call
connectStorageEmulatorin the browser.
Apply:
-if(process.env.NEXT_PUBLIC_USE_FIREBASE_EMULATOR == 'true') {
- connectFirestoreEmulator(
- db,
- process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_HOST ?? 'localhost',
- parseInt(process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_FIRESTORE_PORT ?? '8080')
- );
-
- connectStorageEmulator(
- storage,
- process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_HOST ?? 'localhost',
- parseInt(process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_STORAGE_PORT ?? '9199')
- );
-}
+const useEmulator =
+ process.env.NEXT_PUBLIC_USE_FIREBASE_EMULATOR?.toLowerCase() === 'true' &&
+ process.env.NODE_ENV !== 'production';
+
+if (useEmulator) {
+ const host = (process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_HOST || '').trim() || 'localhost';
+ const firestorePort =
+ Number.parseInt(process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_FIRESTORE_PORT || '', 10) || 8080;
+ const storagePort =
+ Number.parseInt(process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_STORAGE_PORT || '', 10) || 9199;
+
+ connectFirestoreEmulator(db, host, firestorePort);
+
+ if (typeof window !== 'undefined') {
+ connectStorageEmulator(storage, host, storagePort);
+ }
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if(process.env.NEXT_PUBLIC_USE_FIREBASE_EMULATOR == 'true') { | |
| connectFirestoreEmulator( | |
| db, | |
| process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_HOST ?? 'localhost', | |
| parseInt(process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_FIRESTORE_PORT ?? '8080') | |
| ); | |
| // Initialize Storage | |
| let storage: FirebaseStorage; | |
| if (typeof window !== 'undefined') { | |
| storage = getStorage(app); | |
| // Connect to Storage emulator in development | |
| if (process.env.NODE_ENV === 'development' && process.env.NEXT_PUBLIC_USE_FIREBASE_EMULATOR === 'true') { | |
| const emulatorHost = process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_HOST || 'localhost'; | |
| const emulatorPort = process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_STORAGE_PORT || '9199'; | |
| try { | |
| connectStorageEmulator(storage, emulatorHost, parseInt(emulatorPort)); | |
| console.log('Connected to Storage emulator'); | |
| } catch { | |
| // Emulator already connected | |
| console.log('Storage emulator already connected'); | |
| } | |
| } | |
| } else { | |
| storage = getStorage(app); | |
| connectStorageEmulator( | |
| storage, | |
| process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_HOST ?? 'localhost', | |
| parseInt(process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_STORAGE_PORT ?? '9199') | |
| ); | |
| const useEmulator = | |
| process.env.NEXT_PUBLIC_USE_FIREBASE_EMULATOR?.toLowerCase() === 'true' && | |
| process.env.NODE_ENV !== 'production'; | |
| if (useEmulator) { | |
| const host = (process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_HOST || '').trim() || 'localhost'; | |
| const firestorePort = | |
| Number.parseInt(process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_FIRESTORE_PORT || '', 10) || 8080; | |
| const storagePort = | |
| Number.parseInt(process.env.NEXT_PUBLIC_FIREBASE_EMULATOR_STORAGE_PORT || '', 10) || 9199; | |
| connectFirestoreEmulator(db, host, firestorePort); | |
| if (typeof window !== 'undefined') { | |
| connectStorageEmulator(storage, host, storagePort); | |
| } | |
| } |
🤖 Prompt for AI Agents
In lib/firebase.ts around lines 18 to 29, the emulator setup needs hardening:
change the equality check to strict (===) and ensure the emulator is not enabled
in production (guard with process.env.NODE_ENV !== 'production'), treat env vars
that may be empty strings by using a fallback when the value is falsy (e.g.,
envVar || 'localhost'), and parse ports with parseInt(value, 10) and a numeric
fallback if parsing fails; also only call connectStorageEmulator in the browser
(guard with typeof window !== 'undefined') so storage emulator is not invoked on
the server.
Summary by CodeRabbit