feat(blabsy): dev tooling proposal for local Firebase emulator workflow#1036
Conversation
Staging (w3ds-staging) is on the Spark plan and both its Firestore read quota and Storage bucket quota are currently exhausted, which blocks local dev — image uploads in particular. The client already supports emulator mode (NEXT_PUBLIC_USE_EMULATOR), but two gaps made it unusable in practice: - No way to sign in without the QR / eID-wallet flow: add a dev-only /dev-login page that accepts a Firebase custom token, hard-guarded behind isUsingEmulator so it is inert outside emulator mode. - Empty emulator DB signs out any uid without a Firestore user doc: add an api seedEmulator script that creates an auth user + users doc and mints a sign-in token. It refuses to run unless the EMULATOR_HOST env vars are set, so it can never touch staging or prod. Also ignore the emulator debug logs. Note: the Firestore emulator uses port 8080 (hardcoded in app.ts), so run the client on another port in emulator mode, e.g. `pnpm exec next dev -p 8079`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 56 minutes and 25 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR adds local Firebase emulator development infrastructure. A new seed script populates emulators with a dev user account and custom sign-in token. A new dev login page accepts the token from the URL and signs in the user, then redirects to the home page. The ChangesEmulator Development Workflow
Estimated Code Review Effort🎯 2 (Simple) | ⏱️ ~12 minutes Suggested Reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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: 2
🧹 Nitpick comments (1)
platforms/blabsy/api/src/scripts/seedEmulator.ts (1)
57-77: 💤 Low valueConsider merge behavior for idempotency.
The
.set()call without a merge option will overwrite the entire document on each run. For a dev seed script this may be intentional (resetting to a clean state), but if you want true idempotency that preserves any manual changes between runs, consider using.set({...}, { merge: true }).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@platforms/blabsy/api/src/scripts/seedEmulator.ts` around lines 57 - 77, The seed user creation currently calls db.collection("users").doc(UID).set({...}) which overwrites the entire document; to make the script idempotent and preserve manual changes between runs, change the call to include the merge option (i.e., use .set(<data>, { merge: true })) on the same db.collection("users").doc(UID).set invocation for UID/USERNAME in seedEmulator.ts, or alternatively replace with .update(...) if you only want to modify specific fields.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@platforms/blabsy/client/src/pages/dev-login.tsx`:
- Line 31: The call to signInWithCustomToken currently discards the returned
promise (void signInWithCustomToken(token)), so authentication errors never
update UI; change this to properly await or attach a catch to
signInWithCustomToken(token) and on error call the component's error state
updater (e.g., setError) and clear any "signing in" flag (e.g.,
setIsSigningIn(false)); ensure successful resolution continues the normal flow
and failures set a descriptive error message so the UI doesn't stay stuck on
"Signing in…".
- Line 26: Replace the direct window.location.search usage with Next.js router
query access: import and use useRouter(), then read the token from
router.query.token instead of new
URLSearchParams(window.location.search).get('token'); update any
useEffect/useMemo that depends on the token (e.g., the effect where token is
read) to include router.query.token (or router) in its dependency array so it
reacts when the query becomes available; ensure references to token elsewhere
use the router-derived value and remove the window.location import/usage.
---
Nitpick comments:
In `@platforms/blabsy/api/src/scripts/seedEmulator.ts`:
- Around line 57-77: The seed user creation currently calls
db.collection("users").doc(UID).set({...}) which overwrites the entire document;
to make the script idempotent and preserve manual changes between runs, change
the call to include the merge option (i.e., use .set(<data>, { merge: true }))
on the same db.collection("users").doc(UID).set invocation for UID/USERNAME in
seedEmulator.ts, or alternatively replace with .update(...) if you only want to
modify specific fields.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 8806ad05-f1a0-4c28-882d-3bb42b1f4cfc
📒 Files selected for processing (3)
.gitignoreplatforms/blabsy/api/src/scripts/seedEmulator.tsplatforms/blabsy/client/src/pages/dev-login.tsx
| setError('dev-login is only available in emulator mode.'); | ||
| return; | ||
| } | ||
| const token = new URLSearchParams(window.location.search).get('token'); |
There was a problem hiding this comment.
Use router.query instead of window.location.search for Next.js compatibility.
Accessing query parameters via window.location.search can cause SSR/hydration issues and is not idiomatic in Next.js. Use router.query.token instead, which is available during both server and client rendering.
🔧 Proposed fix
- const token = new URLSearchParams(window.location.search).get('token');
+ const token = router.query.token as string | undefined;
if (!token) {
setError('Missing ?token= parameter.');
return;Also update the dependency array:
- }, [signInWithCustomToken]);
+ }, [signInWithCustomToken, router.query.token]);📝 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.
| const token = new URLSearchParams(window.location.search).get('token'); | |
| const token = router.query.token as string | undefined; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@platforms/blabsy/client/src/pages/dev-login.tsx` at line 26, Replace the
direct window.location.search usage with Next.js router query access: import and
use useRouter(), then read the token from router.query.token instead of new
URLSearchParams(window.location.search).get('token'); update any
useEffect/useMemo that depends on the token (e.g., the effect where token is
read) to include router.query.token (or router) in its dependency array so it
reacts when the query becomes available; ensure references to token elsewhere
use the router-derived value and remove the window.location import/usage.
| setError('Missing ?token= parameter.'); | ||
| return; | ||
| } | ||
| void signInWithCustomToken(token); |
There was a problem hiding this comment.
Handle errors from signInWithCustomToken.
The promise returned by signInWithCustomToken is discarded with void, so any errors thrown or rejected will not update the error state. Users will be stuck seeing "Signing in…" indefinitely if authentication fails.
🛡️ Proposed fix
- void signInWithCustomToken(token);
+ signInWithCustomToken(token).catch((err) => {
+ setError(err.message || 'Failed to sign in with custom token.');
+ });📝 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.
| void signInWithCustomToken(token); | |
| signInWithCustomToken(token).catch((err) => { | |
| setError(err.message || 'Failed to sign in with custom token.'); | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@platforms/blabsy/client/src/pages/dev-login.tsx` at line 31, The call to
signInWithCustomToken currently discards the returned promise (void
signInWithCustomToken(token)), so authentication errors never update UI; change
this to properly await or attach a catch to signInWithCustomToken(token) and on
error call the component's error state updater (e.g., setError) and clear any
"signing in" flag (e.g., setIsSigningIn(false)); ensure successful resolution
continues the normal flow and failures set a descriptive error message so the UI
doesn't stay stuck on "Signing in…".
Extends the emulator dev tooling so messaging flows are testable: - seedEmulator: create two dev users and a chat between them (so the messages screen is reachable), via a reusable seedUser helper. The chat is left empty to mirror a fresh "No messages yet" conversation. - dev-login: sign in exactly once. signInWithCustomToken changes identity every render and a failed attempt re-renders via setError, which caused an infinite retry loop on an invalid token; a ref guard fixes it while keeping the dependency listed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Staging (w3ds-staging) is on the Spark plan and both its Firestore read quota and Storage bucket quota are currently exhausted, which blocks local dev — image uploads in particular. The client already supports emulator mode (NEXT_PUBLIC_USE_EMULATOR), but two gaps made it unusable in practice:
Also ignore the emulator debug logs.
Note: the Firestore emulator uses port 8080 (hardcoded in app.ts), so run the client on another port in emulator mode, e.g.
pnpm exec next dev -p 8079.Description of change
Issue Number
Type of change
How the change has been tested
Change checklist
Summary by CodeRabbit