Skip to content

feat(blabsy): dev tooling proposal for local Firebase emulator workflow#1036

Merged
coodos merged 2 commits into
mainfrom
feat/blabsy-emulator-dev-tooling
Jun 15, 2026
Merged

feat(blabsy): dev tooling proposal for local Firebase emulator workflow#1036
coodos merged 2 commits into
mainfrom
feat/blabsy-emulator-dev-tooling

Conversation

@Bekiboo

@Bekiboo Bekiboo commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

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.

Description of change

Issue Number

Type of change

  • Chore (refactoring, build scripts or anything else that isn't user-facing)

How the change has been tested

Change checklist

  • I have ensured that the CI Checks pass locally
  • I have removed any unnecessary logic
  • My code is well documented
  • I have signed my commits
  • My code follows the pattern of the application
  • I have self reviewed my code

Summary by CodeRabbit

  • Chores
    • Updated repository ignore configuration to exclude Firebase and Firestore emulator debug logs from version control
    • Added development utilities for local Firebase emulator testing, including automated seeding of test user data, Firestore documents, and custom token authentication support

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>
@Bekiboo Bekiboo self-assigned this Jun 12, 2026
@Bekiboo Bekiboo requested a review from coodos as a code owner June 12, 2026 11:43
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Bekiboo, we couldn't start this review because you've reached your PR review rate limit.

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7ba06488-c654-4300-b75a-d37b56f07d92

📥 Commits

Reviewing files that changed from the base of the PR and between 9a27097 and cea8196.

📒 Files selected for processing (2)
  • platforms/blabsy/api/src/scripts/seedEmulator.ts
  • platforms/blabsy/client/src/pages/dev-login.tsx
📝 Walkthrough

Walkthrough

This 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 .gitignore is updated to exclude emulator debug logs.

Changes

Emulator Development Workflow

Layer / File(s) Summary
Emulator debug log exclusion
.gitignore
Firebase and Firestore emulator debug log files are added to git exclusions.
Firebase emulator seeding script
platforms/blabsy/api/src/scripts/seedEmulator.ts
Script validates emulator environment variables, loads service account credentials from GOOGLE_APPLICATION_CREDENTIALS, idempotently creates an auth user with a seeded UID, writes a Firestore users/<UID> document with profile fields and timestamps, generates a custom token via createCustomToken, and logs the token with sign-in instructions.
Client dev login page
platforms/blabsy/client/src/pages/dev-login.tsx
Next.js page component reads a token query parameter, validates emulator mode, calls signInWithCustomToken(token) via auth context, tracks local error state, and redirects to /home upon successful login.

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested Reviewers

  • xPathin
  • sosweetham

Poem

🐰 With emulators spinning bright and true,
A seed script whispers: "Dev user, welcome you!"
The login page awaits your token kiss,
Then off to /home with a Firebase bliss.
Local magic, no database miss! 🔥✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding dev tooling (a seedEmulator script and /dev-login page) for a local Firebase emulator workflow, which is the primary objective of this PR.
Description check ✅ Passed The description covers the required template sections: it explains the issue and motivation, specifies 'Chore' as the change type, notes that testing was completed, and all checklist items are marked as completed.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/blabsy-emulator-dev-tooling

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
platforms/blabsy/api/src/scripts/seedEmulator.ts (1)

57-77: 💤 Low value

Consider 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

📥 Commits

Reviewing files that changed from the base of the PR and between 5f08b54 and 9a27097.

📒 Files selected for processing (3)
  • .gitignore
  • platforms/blabsy/api/src/scripts/seedEmulator.ts
  • platforms/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');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Suggested change
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);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Suggested change
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>
@coodos coodos merged commit 4e55007 into main Jun 15, 2026
4 checks passed
@coodos coodos deleted the feat/blabsy-emulator-dev-tooling branch June 15, 2026 10:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants