Skip to content

feat: AI tagging, extension polish, nav/auth UX + security hardening#22

Merged
MinitJain merged 3 commits into
mainfrom
p2-ai-tagging
Mar 28, 2026
Merged

feat: AI tagging, extension polish, nav/auth UX + security hardening#22
MinitJain merged 3 commits into
mainfrom
p2-ai-tagging

Conversation

@MinitJain

@MinitJain MinitJain commented Mar 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add Gemini AI auto-tagging on bookmark save
    (lib/gemini.ts). Tagging failures are non-fatal
    and don't block the save.
  • Extension: brand icons (PNG 16/48/128), "Manage
    your bookmarks →" link to /app, Alt+Shift+S
    keyboard shortcut, fixed host_permissions for
    Vercel
  • Landing page nav: "Sign in" → /auth?mode=login,
    "Get started free" → /auth?mode=signup
  • Auth page: reads ?mode param on load, explicit
    "← Back to home" link below the card
  • Fixed all <img><Image /> ESLint warnings
    across page.tsx, Header, BookmarkCard
  • Added remotePatterns wildcard in next.config.ts
    for external OG thumbnails
  • Ran npm audit fix — 0 vulnerabilities remaining
  • README full rewrite: feature status table, 7-step
    extension install guide, roadmap
  • CLAUDE.md + GUIDE.md: P2.4 AI tagging marked ✅
    Done

Type of change

  • New feature
  • Bug fix
  • Docs / infra

Checklist

  • Code builds without errors (npm run build)
  • No TypeScript errors (npx tsc --noEmit)
  • Lint passes (npm run lint)
  • Self-reviewed the diff
  • Tested manually in the browser

Summary by CodeRabbit

  • New Features

    • AI-powered auto-tagging for newly saved bookmarks
    • Extension keyboard shortcut (Alt+Shift+S) to save the current page
    • Badge feedback for save success/failure and popup “manage” link
  • Improvements

    • Better auth/error handling and clearer save-status messages
    • Updated landing/home visuals and image handling for faster loading
    • Production infra added: Upstash Redis, Vercel Analytics & Speed Insights
  • Documentation

    • README/docs updated: live URL, tech versions (Tailwind v4, Prisma 7), install/run and extension manual-install, roadmap/status updates

- Add Gemini AI auto-tagging on bookmark save (lib/gemini.ts)
- Extension: add brand icon (PNG), manage bookmarks link, Alt+Shift+S shortcut, fix host_permissions for Vercel
- Landing page nav: differentiate Sign in (?mode=login) vs Get started (?mode=signup)
- Auth page: read ?mode param on load, add explicit back-to-home link
- Fix all <img> → <Image /> ESLint warnings (page.tsx, Header, BookmarkCard)
- Add next/image remotePatterns wildcard for external thumbnails
- Run npm audit fix — 0 vulnerabilities remaining
- Update README with full rewrite, extension install guide, feature status
- Update CLAUDE.md and GUIDE.md: P2.4 AI tagging marked done

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented Mar 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
recall Ready Ready Preview, Comment Mar 28, 2026 5:01pm

@coderabbitai

coderabbitai Bot commented Mar 28, 2026

Copy link
Copy Markdown

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key(s) in object: 'instructions'
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
📝 Walkthrough

Walkthrough

Adds AI-generated tag creation into the bookmarks POST flow and returns tags on GET; introduces a Google GenAI client; updates Next.js image config and components; enhances Chrome extension with a save-bookmark command, service worker command handler, UI/UX tweaks, and error handling; and updates documentation and deployment details.

Changes

Cohort / File(s) Summary
Documentation
CLAUDE.md, README.md
Updated tech versions (Tailwind v4, Prisma 7), declared deployment (Vercel live), added Upstash Redis and Vercel Analytics, rewrote roadmap/milestone/state sections, expanded install/run and extension manual-install instructions, updated contributing and acknowledgements.
Next.js image config & components
client/next.config.ts, client/src/components/BookmarkCard.tsx, client/src/components/Header.tsx, client/src/app/page.tsx
Added images.remotePatterns for http/https in Next config; replaced native <img> with next/image in header and bookmark thumbnails; updated auth navigation links to include mode query.
Bookmarks API & AI tagging
client/src/app/api/bookmarks/route.ts, client/src/lib/gemini.ts
Added generateTags() using Google GenAI (gemini-2.5-flash); POST /api/bookmarks calls generateTags and inserts tags via prisma.tag.createMany (skipDuplicates) and returns { ...bookmark, aiTagsFailed }; GET now includes tags.
Auth UI
client/src/app/auth/page.tsx
Auth page now reads mode from query params via useSearchParams, splits into AuthForm + AuthPage, wrapped in Suspense, and adds a back-to-home link.
Extension UI & behavior
extension/manifest.json, extension/popup.html, extension/popup.css, extension/popup.js
Added icons and save-bookmark keyboard command (Alt+Shift+S), added production host permission, added password-visibility toggle UI + handler, added management link, improved 401 detection and save feedback (shows aiTagsFailed message).
Extension background / commands
extension/serviceworker.js
Replaced placeholder worker with MV3 service worker: added getSession() helper and chrome.commands.onCommand handler for save-bookmark that reads active tab, validates URL/session, posts to /api/bookmarks, handles 401 by opening popup, and sets per-tab badges on success/error.

Sequence Diagram

sequenceDiagram
    participant Ext as Extension (User)
    participant API as Recall API
    participant Gemini as Google GenAI
    participant DB as Database (Prisma)

    Ext->>API: POST /api/bookmarks { url, Authorization }
    activate API
    API->>API: Scrape metadata (title, description)
    API->>Gemini: generateTags(title, description)
    activate Gemini
    Gemini-->>API: JSON array of tag strings
    deactivate Gemini
    API->>DB: create bookmark record
    API->>DB: createMany(tags) with bookmarkId (skipDuplicates)
    DB-->>API: persisted bookmark + tags
    API-->>Ext: { bookmark, aiTagsFailed }
    deactivate API
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main changes: AI tagging feature, extension improvements, navigation/auth UX updates, and security hardening.
Description check ✅ Passed The PR description provides comprehensive coverage of all changes, follows the template structure with type selection and completed checklist items, though the summary format is slightly informal.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch p2-ai-tagging

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

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
client/src/app/page.tsx (2)

410-418: ⚠️ Potential issue | 🟡 Minor

Same inconsistency: final CTA also missing mode parameter.

Similar to the hero CTA, this "Start saving for free" link should include ?mode=signup for consistency with the nav behavior.

🔧 Proposed fix
-          <Link href="/auth" style={{
+          <Link href="/auth?mode=signup" style={{
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/app/page.tsx` around lines 410 - 418, The final CTA Link in
page.tsx (the Link element rendering "Start saving for free →") is missing the
mode query param; update its href to include "?mode=signup" (e.g., change href
from "/auth" to "/auth?mode=signup") so it matches the nav/hero CTA behavior and
consistently triggers signup mode in the Auth flow.

118-127: ⚠️ Potential issue | 🟡 Minor

Inconsistent auth link: missing mode parameter.

The hero CTA "Start saving for free" links to /auth without a mode parameter, while the nav links at lines 33-36 correctly use /auth?mode=signup and /auth?mode=login. This inconsistency means this CTA will default to login mode instead of signup.

🔧 Proposed fix for consistency
-            <Link href="/auth" style={{
+            <Link href="/auth?mode=signup" style={{
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/app/page.tsx` around lines 118 - 127, The hero CTA Link currently
points to "/auth" (the Link element rendering "Start saving for free") which is
inconsistent with nav links using "/auth?mode=signup" and causes it to default
to login; update that Link's href to include the signup query parameter (e.g.,
"/auth?mode=signup") so the CTA opens the signup flow, leaving all other inline
styles and attributes unchanged.
🧹 Nitpick comments (4)
client/next.config.ts (1)

4-15: Wildcard hostname configuration is intentional but worth documenting.

The hostname: "**" pattern allows images from any external domain, which is necessary for arbitrary OG thumbnails from bookmarked URLs. Since BookmarkCard uses unoptimized, the images bypass the optimization proxy anyway, reducing SSRF risk.

Consider adding a comment explaining why this permissive configuration is required:

📝 Add explanatory comment
 const nextConfig: NextConfig = {
+  // Allow images from any hostname because bookmark thumbnails
+  // come from arbitrary external websites' OG metadata.
+  // BookmarkCard uses `unoptimized` to bypass the optimization proxy.
   images: {
     remotePatterns: [
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/next.config.ts` around lines 4 - 15, Add a short explanatory comment
above the images.remotePatterns block in next.config.ts that documents why
hostname: "**" is intentionally allowed (to permit arbitrary external OG
thumbnails for bookmarked URLs) and note that BookmarkCard uses unoptimized
images so they bypass the Next image optimization proxy, reducing SSRF risk;
mention any remaining precautions or rationale so future reviewers understand
this permissive configuration and its trade-offs.
client/src/app/auth/page.tsx (1)

248-254: Consider adding a fallback UI to the Suspense boundary.

The Suspense wrapper is correctly required for useSearchParams() in Next.js App Router, but an empty fallback means users see nothing during the brief hydration period. A minimal loading indicator would improve perceived performance.

✨ Optional: Add a loading fallback
 export default function AuthPage() {
   return (
-    <Suspense>
+    <Suspense fallback={<div className="min-h-screen bg-[var(--bg)]" />}>
       <AuthForm />
     </Suspense>
   );
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/app/auth/page.tsx` around lines 248 - 254, AuthPage's Suspense
wrapper has no fallback, causing a blank UI during hydration; add a minimal
fallback (e.g., a Loading text or small spinner) to the Suspense that wraps
AuthForm so users see a loading indicator while useSearchParams()
resolves—update the Suspense in the AuthPage component to include a fallback
prop (or reference a small Loading/Spinner component) so the UI shows
immediately.
client/src/components/BookmarkCard.tsx (1)

106-113: Consider adding error handling for failed image loads.

External thumbnail URLs from OG metadata may return 404, be CORS-blocked, or fail to load for various reasons. Without an onError handler, the component will display a broken image state.

🛡️ Proposed fix to handle image load failures
+import { useState } from "react";
+// ... existing imports

 export default function BookmarkCard({ bookmark }: { bookmark: Bookmark }) {
   const router = useRouter();
   const [input, setInput] = useState("");
+  const [imgError, setImgError] = useState(false);
   // ... rest of state

   // In the render:
-      {bookmark.thumbnail && (
+      {bookmark.thumbnail && !imgError && (
         <Image
           src={bookmark.thumbnail}
           alt={bookmark.title ?? ""}
           width={64}
           height={64}
           className="w-16 h-16 flex-shrink-0 rounded-xl object-cover bg-[var(--surface-2)]"
           unoptimized
+          onError={() => setImgError(true)}
         />
       )}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/components/BookmarkCard.tsx` around lines 106 - 113, The Image in
BookmarkCard using src={bookmark.thumbnail} lacks error handling and can show a
broken image when remote thumbnails fail; update the BookmarkCard component to
add an onError handler (or local state-managed fallbackSrc) that swaps the image
to a safe local placeholder (e.g., a bundled SVG/PNG) or hides the image when
loading fails, ensure the handler guards against infinite replacement loops, and
reference the Image element using bookmark.thumbnail and alt={bookmark.title} so
the fallback is applied only for this card.
extension/serviceworker.js (1)

41-43: Avoid fully silent network failures in the command path.

Lines [41]-[43] swallow all fetch errors. Add lightweight telemetry (e.g., console.warn in dev or a debug flag) so outages/auth issues are diagnosable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@extension/serviceworker.js` around lines 41 - 43, The current catch block
after the network fetch in serviceworker.js silently swallows all errors; update
the catch in the try/catch around the fetch so it emits lightweight telemetry
(e.g., call console.warn or a debug logger with the caught Error) but only when
in dev or when a debug flag is enabled (check an existing debug flag or use
self.__DEV__ / a configurable DEBUG constant); include the error.message and a
short context string (e.g., "serviceworker fetch failed for <operation>") so
outages/auth issues can be diagnosed without leaking in production.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@client/src/lib/gemini.ts`:
- Line 3: The module currently uses a non-null assertion when creating the
GoogleGenAI client (const ai = new GoogleGenAI({ apiKey:
process.env.GEMINI_API_KEY! })), which causes opaque import-time failures if
GEMINI_API_KEY is missing; change this to either (a) lazy-initialize the client
via a getClient() helper that constructs GoogleGenAI on first use (and call
getClient() from generateTags), or (b) perform early validation at module
initialization: check process.env.GEMINI_API_KEY and throw a clear, descriptive
error if missing before constructing GoogleGenAI; remove the non-null assertion
and ensure the chosen approach references the GoogleGenAI instantiation and
generateTags usage.

In `@extension/serviceworker.js`:
- Around line 21-23: The current check only verifies tab.url exists and can pass
non-web schemes to your backend; update the logic after chrome.tabs.query (the
const [tab] = await chrome.tabs.query(...) block) to validate the URL protocol
is http or https (e.g., inspect tab.url's protocol via URL or
startsWith('http://')/startsWith('https://')) and return early if it is not, and
apply the same validation at the other occurrence around the POST call (the
similar check at line ~31) so only http/https pages are forwarded to the
backend.
- Line 17: Calls to chrome.action.openPopup() and the chrome.action badge APIs
are not handling returned Promises and tab.id is used without explicit
validation; update the service worker to await or attach .catch handlers to
chrome.action.openPopup() and all chrome.action.* calls (e.g.,
chrome.action.setBadgeText, chrome.action.setBadgeBackgroundColor) so rejections
are not unhandled, and before performing badge operations validate that the tab
object has a numeric id (e.g., typeof tab.id === "number") and only call badge
APIs when that check passes; apply these changes around the existing
chrome.action.openPopup() call and the badge-related code blocks that reference
tab.id.

---

Outside diff comments:
In `@client/src/app/page.tsx`:
- Around line 410-418: The final CTA Link in page.tsx (the Link element
rendering "Start saving for free →") is missing the mode query param; update its
href to include "?mode=signup" (e.g., change href from "/auth" to
"/auth?mode=signup") so it matches the nav/hero CTA behavior and consistently
triggers signup mode in the Auth flow.
- Around line 118-127: The hero CTA Link currently points to "/auth" (the Link
element rendering "Start saving for free") which is inconsistent with nav links
using "/auth?mode=signup" and causes it to default to login; update that Link's
href to include the signup query parameter (e.g., "/auth?mode=signup") so the
CTA opens the signup flow, leaving all other inline styles and attributes
unchanged.

---

Nitpick comments:
In `@client/next.config.ts`:
- Around line 4-15: Add a short explanatory comment above the
images.remotePatterns block in next.config.ts that documents why hostname: "**"
is intentionally allowed (to permit arbitrary external OG thumbnails for
bookmarked URLs) and note that BookmarkCard uses unoptimized images so they
bypass the Next image optimization proxy, reducing SSRF risk; mention any
remaining precautions or rationale so future reviewers understand this
permissive configuration and its trade-offs.

In `@client/src/app/auth/page.tsx`:
- Around line 248-254: AuthPage's Suspense wrapper has no fallback, causing a
blank UI during hydration; add a minimal fallback (e.g., a Loading text or small
spinner) to the Suspense that wraps AuthForm so users see a loading indicator
while useSearchParams() resolves—update the Suspense in the AuthPage component
to include a fallback prop (or reference a small Loading/Spinner component) so
the UI shows immediately.

In `@client/src/components/BookmarkCard.tsx`:
- Around line 106-113: The Image in BookmarkCard using src={bookmark.thumbnail}
lacks error handling and can show a broken image when remote thumbnails fail;
update the BookmarkCard component to add an onError handler (or local
state-managed fallbackSrc) that swaps the image to a safe local placeholder
(e.g., a bundled SVG/PNG) or hides the image when loading fails, ensure the
handler guards against infinite replacement loops, and reference the Image
element using bookmark.thumbnail and alt={bookmark.title} so the fallback is
applied only for this card.

In `@extension/serviceworker.js`:
- Around line 41-43: The current catch block after the network fetch in
serviceworker.js silently swallows all errors; update the catch in the try/catch
around the fetch so it emits lightweight telemetry (e.g., call console.warn or a
debug logger with the caught Error) but only when in dev or when a debug flag is
enabled (check an existing debug flag or use self.__DEV__ / a configurable DEBUG
constant); include the error.message and a short context string (e.g.,
"serviceworker fetch failed for <operation>") so outages/auth issues can be
diagnosed without leaking in production.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dac0dd77-adf4-46d8-9c57-454acb5110b0

📥 Commits

Reviewing files that changed from the base of the PR and between b28e98f and c519a71.

⛔ Files ignored due to path filters (4)
  • client/package-lock.json is excluded by !**/package-lock.json
  • extension/icon128.png is excluded by !**/*.png
  • extension/icon16.png is excluded by !**/*.png
  • extension/icon48.png is excluded by !**/*.png
📒 Files selected for processing (14)
  • CLAUDE.md
  • README.md
  • client/next.config.ts
  • client/src/app/api/bookmarks/route.ts
  • client/src/app/auth/page.tsx
  • client/src/app/page.tsx
  • client/src/components/BookmarkCard.tsx
  • client/src/components/Header.tsx
  • client/src/lib/gemini.ts
  • extension/manifest.json
  • extension/popup.css
  • extension/popup.html
  • extension/popup.js
  • extension/serviceworker.js

Comment thread client/src/lib/gemini.ts Outdated
Comment thread extension/serviceworker.js Outdated
Comment thread extension/serviceworker.js
- gemini.ts: replace module-level non-null assertion with lazy getClient()
  helper that validates GEMINI_API_KEY and throws a clear error if missing
- serviceworker.js: add .catch(() => {}) to all chrome.action.openPopup()
  and badge API calls to prevent unhandled promise rejections
- serviceworker.js: validate tab.id is a number before passing to badge APIs
- serviceworker.js: validate URL protocol is http/https before forwarding
  to the backend, rejecting chrome://, file://, etc.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@extension/serviceworker.js`:
- Around line 39-50: The current response handling swallows all non-OK responses
except 401 and the catch block silently ignores network errors; update the block
that checks res (the code using res, tabId, chrome.action.setBadgeText,
chrome.action.setBadgeBackgroundColor, and chrome.action.openPopup) so that any
non-ok status (e.g., 400, 429, 500) visibly surfaces failure: set a distinct
badge (e.g., "!" or "✖") with a red background for tabId, keep the badge for a
few seconds (use the same setTimeout clearing logic), and optionally call
chrome.action.openPopup() or another user-visible notification for serious
errors; also ensure the catch block similarly sets the error badge when tabId is
defined instead of silently returning.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5c192b5d-6184-4fe3-b8a1-35db7e67c39b

📥 Commits

Reviewing files that changed from the base of the PR and between c519a71 and cde967d.

📒 Files selected for processing (2)
  • client/src/lib/gemini.ts
  • extension/serviceworker.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • client/src/lib/gemini.ts

Comment thread extension/serviceworker.js
Non-OK responses (400, 429, 500) and network errors now show a red ✖
badge for 3 seconds instead of silently doing nothing. 401 still opens
the popup. Success keeps the existing gold ✓ badge.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
extension/serviceworker.js (3)

47-59: Extract duplicated error badge logic into a helper.

The error badge logic (lines 48-52 and 55-58) is identical. Extracting a helper improves maintainability.

Suggested refactor
+function showErrorBadge(tabId) {
+  if (tabId === undefined) return;
+  chrome.action.setBadgeText({ text: "✖", tabId }).catch(() => {});
+  chrome.action.setBadgeBackgroundColor({ color: "#EF4444", tabId }).catch(() => {});
+  setTimeout(() => chrome.action.setBadgeText({ text: "", tabId }).catch(() => {}), 3000);
+}
+
 chrome.commands.onCommand.addListener(async (command) => {
   // ... existing code ...
     } else {
-      if (tabId !== undefined) {
-        chrome.action.setBadgeText({ text: "✖", tabId }).catch(() => {});
-        chrome.action.setBadgeBackgroundColor({ color: "#EF4444", tabId }).catch(() => {});
-        setTimeout(() => chrome.action.setBadgeText({ text: "", tabId }).catch(() => {}), 3000);
-      }
+      showErrorBadge(tabId);
     }
   } catch {
-    if (tabId !== undefined) {
-      chrome.action.setBadgeText({ text: "✖", tabId }).catch(() => {});
-      chrome.action.setBadgeBackgroundColor({ color: "#EF4444", tabId }).catch(() => {});
-      setTimeout(() => chrome.action.setBadgeText({ text: "", tabId }).catch(() => {}), 3000);
-    }
+    showErrorBadge(tabId);
   }
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@extension/serviceworker.js` around lines 47 - 59, The duplicated error badge
code that calls chrome.action.setBadgeText and
chrome.action.setBadgeBackgroundColor and the setTimeout appears twice; extract
this into a helper (e.g., showErrorBadge(tabId)) that takes tabId, performs the
three operations with the same .catch handlers, and replace both duplicated
blocks with a call to that helper where tabId !== undefined; update any
surrounding scope so the helper can access chrome and tabId as needed.

24-25: Consider wrapping URL parsing in try-catch.

new URL(tab.url) can throw TypeError on malformed URLs. While Chrome typically provides valid URLs, wrapping this in a try-catch adds defensive protection.

Suggested diff
-  const protocol = new URL(tab.url).protocol;
-  if (protocol !== "http:" && protocol !== "https:") return;
+  let protocol;
+  try {
+    protocol = new URL(tab.url).protocol;
+  } catch {
+    return;
+  }
+  if (protocol !== "http:" && protocol !== "https:") return;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@extension/serviceworker.js` around lines 24 - 25, Wrap the URL parsing that
uses new URL(tab.url) in a try-catch to defensively handle malformed URLs: catch
the TypeError thrown by new URL(tab.url), optionally log or ignore the error,
and return early instead of letting it crash; then keep the existing protocol
check (protocol !== "http:" && protocol !== "https:") unchanged. Target the code
around the protocol assignment (the new URL(tab.url) call) in serviceworker.js
and ensure any error path exits the handler cleanly.

1-3: Remove unused constants.

SUPABASE_URL and SUPABASE_ANON_KEY are declared but never used in this file. Only API_BASE is referenced (line 30). Consider removing the dead code to reduce confusion.

Suggested diff
-const SUPABASE_URL = "https://gfdwrzaeofehgpwuulvr.supabase.co";
-const SUPABASE_ANON_KEY = "sb_publishable_PLZj21S_KtFVCz1-jiq5PQ_3WNyg3dQ";
 const API_BASE = "https://recallsave.vercel.app";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@extension/serviceworker.js` around lines 1 - 3, SUPABASE_URL and
SUPABASE_ANON_KEY are dead declarations and should be removed to avoid
confusion; delete the const declarations for SUPABASE_URL and SUPABASE_ANON_KEY
and keep only the API_BASE constant (used elsewhere, e.g., in the fetch logic
that references API_BASE) so the file only declares the actually used symbol.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@extension/serviceworker.js`:
- Around line 47-59: The duplicated error badge code that calls
chrome.action.setBadgeText and chrome.action.setBadgeBackgroundColor and the
setTimeout appears twice; extract this into a helper (e.g.,
showErrorBadge(tabId)) that takes tabId, performs the three operations with the
same .catch handlers, and replace both duplicated blocks with a call to that
helper where tabId !== undefined; update any surrounding scope so the helper can
access chrome and tabId as needed.
- Around line 24-25: Wrap the URL parsing that uses new URL(tab.url) in a
try-catch to defensively handle malformed URLs: catch the TypeError thrown by
new URL(tab.url), optionally log or ignore the error, and return early instead
of letting it crash; then keep the existing protocol check (protocol !== "http:"
&& protocol !== "https:") unchanged. Target the code around the protocol
assignment (the new URL(tab.url) call) in serviceworker.js and ensure any error
path exits the handler cleanly.
- Around line 1-3: SUPABASE_URL and SUPABASE_ANON_KEY are dead declarations and
should be removed to avoid confusion; delete the const declarations for
SUPABASE_URL and SUPABASE_ANON_KEY and keep only the API_BASE constant (used
elsewhere, e.g., in the fetch logic that references API_BASE) so the file only
declares the actually used symbol.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 013d16cf-7c7f-400f-990a-80688aa76c68

📥 Commits

Reviewing files that changed from the base of the PR and between cde967d and 5a31319.

📒 Files selected for processing (1)
  • extension/serviceworker.js

@MinitJain MinitJain merged commit f57cc2d into main Mar 28, 2026
4 checks passed
@MinitJain MinitJain deleted the p2-ai-tagging branch March 29, 2026 12:33
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.

1 participant