Skip to content

feat: beta label, feedback modal, and privacy update - #24

Merged
holkexyz merged 9 commits into
mainfrom
staging
Apr 2, 2026
Merged

feat: beta label, feedback modal, and privacy update#24
holkexyz merged 9 commits into
mainfrom
staging

Conversation

@holkexyz

@holkexyz holkexyz commented Apr 2, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds a "beta" label next to the Certified wordmark in the navbar
  • Adds a floating "Share Feedback" button with modal for submitting feedback via email (Resend)
  • Feedback sent to support@hypercerts.org; optional confirmation email to user
  • Mobile bottom sheet with drag handle (reuses existing bottom-sheet component)
  • Form content persists when closing/reopening; success screen with "More Feedback" option
  • Updates privacy policy with Vercel Web Analytics disclosure
  • Adds section 5 (Group and organization accounts) to Terms of Service
  • Hardens CSRF origin check with strict hostname comparison
  • Fixes ARIA dialog attributes placement for accessibility

Setup

  • Requires RESEND_API_KEY env var (already added to Vercel Production + Preview)
  • Optional RESEND_FROM_EMAIL override (defaults to Certified <no-reply@certified.one>)

Test plan

  • Verify "beta" label appears next to wordmark in navbar
  • Click "Share Feedback" button, confirm modal opens and button hides
  • Submit feedback without email — check support@hypercerts.org receives it
  • Submit feedback with email — check both support and user receive emails
  • Test email validation on the optional field
  • Click "More Feedback" on success screen to submit again
  • Close and reopen modal — form content should persist
  • Scroll to bottom — feedback button stays above footer
  • Test expand/shrink toggle on desktop
  • Test mobile: bottom sheet with drag handle, swipe up to expand, swipe down to dismiss
  • Verify privacy policy at /privacy includes Vercel Web Analytics section
  • Verify terms at /terms includes section 5 (Group and organization accounts)
  • Verify all ToS section numbers and cross-references are correct

🤖 Generated with Claude Code

holkexyz and others added 7 commits April 1, 2026 14:43
- Add "beta" label next to the Certified wordmark in navbar
- Add floating "Share Feedback" button (bottom-right) that opens a modal
- Feedback modal includes message textarea and optional email field with validation
- API route sends feedback to support@hypercerts.org via Resend
- Sends confirmation email to user if they provide an email address
- Feedback button stays above footer when scrolled to bottom
- Modal has expand/shrink toggle on desktop

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add "beta" label next to the Certified wordmark in navbar
- Add floating "Share Feedback" button (bottom-right) that opens a modal
- Feedback modal includes message textarea and optional email field with validation
- API route sends feedback to support@hypercerts.org via Resend
- Sends confirmation email to user if they provide an email address
- Feedback button stays above footer when scrolled to bottom
- Modal has expand/shrink toggle on desktop

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Hide trigger button when modal is open
- Add visual feedback when swiping up to expand
- Persist form content when closing and reopening
- Increase handle touch target size

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
certified-app Ready Ready Preview, Comment Apr 2, 2026 1:52am

Request Review

@coderabbitai

coderabbitai Bot commented Apr 2, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a client-side feedback modal (desktop overlay + mobile bottom-sheet), a POST API endpoint that sends emails via Resend, example env vars and dependency for Resend, CSS for modal/UI, a navbar beta label, and privacy text updates disclosing Vercel analytics.

Changes

Cohort / File(s) Summary
Environment & Dependency
\.env\.local\.example, package\.json
Added commented RESEND_API_KEY and RESEND_FROM_EMAIL entries to example env; added resend@^6.10.0 dependency.
Feedback API
src/app/api/feedback/route.ts
New POST handler validating origin, message, optional email; sends support email (to support@hypercerts.org) and optional confirmation to user via Resend; logs and returns proper HTTP errors.
Feedback UI Component
src/components/ui/feedback-modal.tsx
New client React component: floating trigger, desktop modal, mobile bottom-sheet with drag/keyboard/viewport handling, form validation, POST to /api/feedback, success and error states.
Styling
src/app/globals.css
Added extensive CSS for trigger, modal, backdrop, expanded variant, mobile bottom-sheet, form elements; adjusted navbar bottom-sheet handle padding.
Layout & Navbar
src/app/layout.tsx, src/components/layout/navbar.tsx
Mounted <FeedbackModal /> in root layout; added visible .navbar__beta-label element next to logo.
Privacy Page
src/app/privacy/page.tsx
Updated last-updated date and disclosures: added Vercel Inc. to data-sharing list and explicit Vercel Web Analytics description (anonymous, no cookies, SCCs).
sequenceDiagram
    actor User
    participant Client as Feedback Modal (Client)
    participant Server as /api/feedback (Server)
    participant Resend as Resend (Email Service)

    User->>Client: Open modal, enter message (and optional email)
    User->>Client: Submit form
    Client->>Client: Validate message and email
    alt Validation fails
        Client->>User: Show inline error
    else Validation passes
        Client->>Server: POST /api/feedback {message, email?}
        Server->>Server: Check origin/host and validate payload
        alt Invalid request
            Server-->>Client: 400/403 response
            Client->>User: Show error
        else Valid
            Server->>Resend: Send support email to support@hypercerts.org
            Resend-->>Server: Acknowledgement
            alt email provided
                Server->>Resend: Send confirmation email to user
                Resend-->>Server: Acknowledgement
            end
            Server-->>Client: { success: true }
            Client->>User: Show confirmation view
        end
    end
Loading

🎯 4 (Complex) | ⏱️ ~50 minutes

🐰 I hopped a note into the night,
Pushed a modal, soft and light,
Resend carried letters true,
Beta badge gave a cheerful cue,
Thank yous sent — a small carrot delight.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 summarizes the three main features added in this PR: a beta label in the navbar, a feedback modal with Resend integration, and privacy policy updates.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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 staging

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: 6

🧹 Nitpick comments (2)
src/app/api/feedback/route.ts (1)

36-54: Consider graceful handling if confirmation email fails.

If the support email succeeds (line 21-33) but the user confirmation email fails, the entire request returns 500. The user's feedback was received, but they get an error. Consider handling the confirmation email failure gracefully.

Proposed approach
     // Send confirmation to user if they provided an email
     if (email) {
-      await resend.emails.send({
+      try {
+        await resend.emails.send({
-        from: FROM_EMAIL,
-        to: email,
-        subject: "Thank you for your feedback to Certified.app",
-        text: [
-          "Thank you for sharing your feedback with us!",
-          "",
-          "We've received the following message:",
-          "",
-          `"${message}"`,
-          "",
-          "We appreciate your input and will review it carefully.",
-          "",
-          "Best regards,",
-          "The Certified Team",
-        ].join("\n"),
-      });
+          from: FROM_EMAIL,
+          to: email,
+          subject: "Thank you for your feedback to Certified.app",
+          text: [
+            "Thank you for sharing your feedback with us!",
+            "",
+            "We've received the following message:",
+            "",
+            `"${message}"`,
+            "",
+            "We appreciate your input and will review it carefully.",
+            "",
+            "Best regards,",
+            "The Certified Team",
+          ].join("\n"),
+        });
+      } catch (confirmErr) {
+        console.error("Failed to send confirmation email:", confirmErr);
+        // Don't fail the request - feedback was received
+      }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/api/feedback/route.ts` around lines 36 - 54, Wrap the
user-confirmation email send (the resend.emails.send call that uses FROM_EMAIL
and to: email) in a try/catch so failure to send the confirmation does not
bubble up and turn the whole request into a 500; after catching, log the error
(use existing logger or console.error) with context like "confirmation email
failed" and continue returning the normal success response (the same response
you return when the support email succeeds).
src/components/ui/feedback-modal.tsx (1)

66-73: Consider returning focus to trigger when modal closes via Escape.

The Escape key handler closes the modal but doesn't return focus to the trigger button. For better keyboard accessibility, focus should be restored to the element that opened the modal.

Proposed approach
+  const triggerRef = useRef<HTMLButtonElement>(null)
+
   useEffect(() => {
     if (!isOpen) return
     const handleKeyDown = (e: KeyboardEvent) => {
-      if (e.key === "Escape") setIsOpen(false)
+      if (e.key === "Escape") {
+        setIsOpen(false)
+        setTimeout(() => triggerRef.current?.focus(), 0)
+      }
     }
     document.addEventListener("keydown", handleKeyDown)
     return () => document.removeEventListener("keydown", handleKeyDown)
   }, [isOpen])

And add ref={triggerRef} to the trigger button.

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

In `@src/components/ui/feedback-modal.tsx` around lines 66 - 73, The Escape
handler in the useEffect closes the modal but doesn't restore focus; store a ref
to the trigger element (e.g., add triggerRef and attach it to the trigger
button) and when handling Escape/closing (in handleKeyDown or wherever
setIsOpen(false) is invoked) call triggerRef.current?.focus() after closing;
update the useEffect/handleKeyDown logic in the feedback-modal component
(useEffect, handleKeyDown, setIsOpen) to capture and restore focus so keyboard
users return to the trigger when the modal closes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.env.local.example:
- Line 24: Update the example RESEND_FROM_EMAIL in .env.local.example to match
the actual default used in the code (change noreply@certified.one to
no-reply@certified.one) so developers aren't confused; ensure the
RESEND_FROM_EMAIL example value matches the default email string used in
route.ts (the code path that falls back to the env var/default).

In `@src/app/api/feedback/route.ts`:
- Around line 8-14: Add a CSRF Origin check at the start of the POST handler
(function POST) by reading the request Origin header (req.headers.get("origin"))
and validating it against the allowed origin(s) or the app's expected host; if
the origin is missing or not allowed, return NextResponse.json({ error: "Invalid
origin" }, { status: 403 }) before processing the payload. Ensure this
validation happens before parsing req.json() and before any other logic so the
handler rejects cross-site requests early; update any config/constant used for
allowed origins and reference it from the POST function for maintainability.
- Line 4: Resend client is initialized unconditionally which hides missing API
key errors; before constructing the Resend instance (the const resend = new
Resend(...) line) validate process.env.RESEND_API_KEY and fail fast with a clear
message or throw an error (or alternatively check inside the request handler and
return a helpful 4xx error) so that the Resend class is not instantiated with an
undefined key; update the code around the Resend initialization (referencing the
Resend symbol and RESEND_API_KEY env var) to validate and handle the missing key
explicitly.

In `@src/app/globals.css`:
- Around line 183-194: The .navbar__beta-label rule violates styling guidelines:
remove or neutralize the uppercase transformation by deleting text-transform:
uppercase (or set text-transform: none) in the .navbar__beta-label CSS, and
replace the hard-coded border-radius: 4px with border-radius: var(--radius) so
the component uses the shared radius variable.

In `@src/components/ui/feedback-modal.tsx`:
- Around line 240-242: The error paragraphs rendering emailError and error
currently lack ARIA roles; update the two JSX elements that render emailError
and error (the ones using the variables emailError and error and className
"feedback-modal__error") to include role="alert" so screen readers announce them
immediately; ensure both conditional renders include the attribute (e.g., <p
role="alert" ...>) without changing surrounding markup or styling.
- Around line 302-321: The mobile bottom sheet created via createPortal is
missing ARIA dialog semantics, so add appropriate accessibility attributes to
the bottom-sheet container: set role="dialog", aria-modal="true" and an
accessible label/ description (aria-labelledby or aria-label) on the div with
className `bottom-sheet feedback-bottom-sheet` (the element referenced by
sheetRef), and ensure focus management moves focus into that element when opened
and returns focus on close; also mirror any existing desktop modal IDs used for
labels to reuse the same label element for consistency.

---

Nitpick comments:
In `@src/app/api/feedback/route.ts`:
- Around line 36-54: Wrap the user-confirmation email send (the
resend.emails.send call that uses FROM_EMAIL and to: email) in a try/catch so
failure to send the confirmation does not bubble up and turn the whole request
into a 500; after catching, log the error (use existing logger or console.error)
with context like "confirmation email failed" and continue returning the normal
success response (the same response you return when the support email succeeds).

In `@src/components/ui/feedback-modal.tsx`:
- Around line 66-73: The Escape handler in the useEffect closes the modal but
doesn't restore focus; store a ref to the trigger element (e.g., add triggerRef
and attach it to the trigger button) and when handling Escape/closing (in
handleKeyDown or wherever setIsOpen(false) is invoked) call
triggerRef.current?.focus() after closing; update the useEffect/handleKeyDown
logic in the feedback-modal component (useEffect, handleKeyDown, setIsOpen) to
capture and restore focus so keyboard users return to the trigger when the modal
closes.
🪄 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: a8fcd550-8fd0-4f74-866d-6c52e07c4aa3

📥 Commits

Reviewing files that changed from the base of the PR and between 27121fe and 8eaa164.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • .env.local.example
  • package.json
  • src/app/api/feedback/route.ts
  • src/app/globals.css
  • src/app/layout.tsx
  • src/app/privacy/page.tsx
  • src/components/layout/navbar.tsx
  • src/components/ui/feedback-modal.tsx

Comment thread .env.local.example Outdated
import { NextRequest, NextResponse } from "next/server";
import { Resend } from "resend";

const resend = new Resend(process.env.RESEND_API_KEY);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add validation for missing API key.

If RESEND_API_KEY is not set, the Resend client initialization succeeds but email sending will fail at runtime with an unclear error. Consider failing fast with a clear message.

Proposed fix
+if (!process.env.RESEND_API_KEY) {
+  console.warn("RESEND_API_KEY is not set - feedback emails will fail");
+}
+
 const resend = new Resend(process.env.RESEND_API_KEY);

Or alternatively, return a more helpful error in the handler if the key is missing.

📝 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 resend = new Resend(process.env.RESEND_API_KEY);
if (!process.env.RESEND_API_KEY) {
console.warn("RESEND_API_KEY is not set - feedback emails will fail");
}
const resend = new Resend(process.env.RESEND_API_KEY);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/api/feedback/route.ts` at line 4, Resend client is initialized
unconditionally which hides missing API key errors; before constructing the
Resend instance (the const resend = new Resend(...) line) validate
process.env.RESEND_API_KEY and fail fast with a clear message or throw an error
(or alternatively check inside the request handler and return a helpful 4xx
error) so that the Resend class is not instantiated with an undefined key;
update the code around the Resend initialization (referencing the Resend symbol
and RESEND_API_KEY env var) to validate and handle the missing key explicitly.

Comment thread src/app/api/feedback/route.ts
Comment thread src/app/globals.css
Comment on lines +183 to +194
.navbar__beta-label {
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--color-dark-gray);
background: var(--color-gray-100);
padding: 1px 6px;
border-radius: 4px;
margin-left: 10px;
line-height: 1;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Guideline violations in beta label styling.

Two issues with this CSS:

  1. text-transform: uppercase on line 186 violates the guideline "do not use uppercase text anywhere."
  2. border-radius: 4px on line 191 should use var(--radius) per the guideline "Use var(--radius) (4px) for all border-radius values."
Proposed fix
 .navbar__beta-label {
   font-size: 10px;
   font-weight: 600;
-  text-transform: uppercase;
   letter-spacing: 0.05em;
   color: var(--color-dark-gray);
   background: var(--color-gray-100);
   padding: 1px 6px;
-  border-radius: 4px;
+  border-radius: var(--radius);
   margin-left: 10px;
   line-height: 1;
 }

As per coding guidelines: "do not use uppercase text anywhere" and "Use var(--radius) (4px) for all border-radius values."

📝 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
.navbar__beta-label {
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--color-dark-gray);
background: var(--color-gray-100);
padding: 1px 6px;
border-radius: 4px;
margin-left: 10px;
line-height: 1;
}
.navbar__beta-label {
font-size: 10px;
font-weight: 600;
letter-spacing: 0.05em;
color: var(--color-dark-gray);
background: var(--color-gray-100);
padding: 1px 6px;
border-radius: var(--radius);
margin-left: 10px;
line-height: 1;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/globals.css` around lines 183 - 194, The .navbar__beta-label rule
violates styling guidelines: remove or neutralize the uppercase transformation
by deleting text-transform: uppercase (or set text-transform: none) in the
.navbar__beta-label CSS, and replace the hard-coded border-radius: 4px with
border-radius: var(--radius) so the component uses the shared radius variable.

Comment thread src/components/ui/feedback-modal.tsx Outdated
Comment thread src/components/ui/feedback-modal.tsx
- Fix email typo in .env.local.example (noreply → no-reply)
- Add RESEND_API_KEY warning when missing
- Add CSRF origin check on feedback POST route
- Add role="alert" to error messages for accessibility
- Add ARIA attributes to mobile bottom sheet

Co-Authored-By: Claude Opus 4.6 (1M context) <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: 2

🧹 Nitpick comments (2)
src/app/api/feedback/route.ts (1)

46-65: Consider handling confirmation email failure gracefully.

If the support email (lines 32-44) succeeds but the confirmation email fails, the request returns a 500 error even though the primary feedback was delivered. The user may retry and submit duplicate feedback.

Optional: Log confirmation failure without failing the request
     // Send confirmation to user if they provided an email
     if (email) {
+      try {
         await resend.emails.send({
           from: FROM_EMAIL,
           to: email,
           subject: "Thank you for your feedback to Certified.app",
           text: [
             "Thank you for sharing your feedback with us!",
             "",
             "We've received the following message:",
             "",
             `"${message}"`,
             "",
             "We appreciate your input and will review it carefully.",
             "",
             "Best regards,",
             "The Certified Team",
           ].join("\n"),
         });
+      } catch (confirmError) {
+        console.error("Confirmation email failed:", confirmError);
+        // Don't fail the request - feedback was already delivered
+      }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/api/feedback/route.ts` around lines 46 - 65, Wrap the confirmation
email send (resend.emails.send using FROM_EMAIL, to: email, subject/body
referencing message) in a try/catch so failures to send the confirmation do not
cause the whole request to fail; on catch, log the error with a clear message
including the email address and error details (using existing logger or
console.error) and continue to return the successful response for the primary
feedback submission instead of rethrowing the error.
src/components/ui/feedback-modal.tsx (1)

262-262: Add aria-hidden="true" to decorative icons.

The icons on these lines are decorative (accompanied by text or within buttons with aria-label) and should be hidden from assistive technology. As per coding guidelines: "aria-hidden=\"true\" on decorative elements."

Proposed fix
-        <MessageSquare size={16} />
+        <MessageSquare size={16} aria-hidden="true" />
-                  {expanded ? <Minimize2 size={14} /> : <Maximize2 size={14} />}
+                  {expanded ? <Minimize2 size={14} aria-hidden="true" /> : <Maximize2 size={14} aria-hidden="true" />}
-                  <X size={16} />
+                  <X size={16} aria-hidden="true" />

Also applies to: 284-284, 292-292

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

In `@src/components/ui/feedback-modal.tsx` at line 262, The decorative icon
components in the feedback modal (e.g., MessageSquare and the other icon
components rendered at the mentioned locations) should be hidden from assistive
tech; update each icon element in src/components/ui/feedback-modal.tsx to
include aria-hidden="true" (for example <MessageSquare aria-hidden="true" />)
and ensure you only add this when the icon is truly decorative (do not add it to
icons that convey unique information or are the sole accessible label).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/api/feedback/route.ts`:
- Around line 14-19: The origin/host substring check in route.ts (variables
origin and host, returning NextResponse.json on failure) is vulnerable to
substring/subdomain spoofing; replace the includes(...) logic with a strict
hostname comparison by parsing origin with the URL constructor (or equivalent)
and comparing parsedOrigin.hostname strictly to the request host's hostname
(strip port from host via split or URL) and return 403 if parsing fails or
hostnames do not match; ensure you handle absent headers and wrap URL parsing in
try/catch to reject malformed origins.

In `@src/components/ui/feedback-modal.tsx`:
- Around line 269-277: The dialog ARIA attributes are placed on the backdrop
instead of the modal content; move role="dialog" and aria-modal="true" (and
aria-label if it labels the dialog) from the backdrop div that uses backdropRef
and the onClick handler to the inner container element with className
"feedback-modal" (the element that conditionally applies
feedback-modal--expanded and uses the expanded prop) so screen readers announce
the actual dialog content; keep the backdropRef, onClick logic and styling on
the backdrop div and ensure the inner .feedback-modal receives the accessible
attributes.

---

Nitpick comments:
In `@src/app/api/feedback/route.ts`:
- Around line 46-65: Wrap the confirmation email send (resend.emails.send using
FROM_EMAIL, to: email, subject/body referencing message) in a try/catch so
failures to send the confirmation do not cause the whole request to fail; on
catch, log the error with a clear message including the email address and error
details (using existing logger or console.error) and continue to return the
successful response for the primary feedback submission instead of rethrowing
the error.

In `@src/components/ui/feedback-modal.tsx`:
- Line 262: The decorative icon components in the feedback modal (e.g.,
MessageSquare and the other icon components rendered at the mentioned locations)
should be hidden from assistive tech; update each icon element in
src/components/ui/feedback-modal.tsx to include aria-hidden="true" (for example
<MessageSquare aria-hidden="true" />) and ensure you only add this when the icon
is truly decorative (do not add it to icons that convey unique information or
are the sole accessible label).
🪄 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: 8b805549-3e5d-4397-bfe1-2f247d525723

📥 Commits

Reviewing files that changed from the base of the PR and between 8eaa164 and b9a05fd.

📒 Files selected for processing (3)
  • .env.local.example
  • src/app/api/feedback/route.ts
  • src/components/ui/feedback-modal.tsx
✅ Files skipped from review due to trivial changes (1)
  • .env.local.example

Comment thread src/app/api/feedback/route.ts
Comment thread src/components/ui/feedback-modal.tsx Outdated
- Replace substring CSRF origin check with strict hostname comparison
- Move dialog ARIA attributes from backdrop to modal content element
- Add section 5 (Group and organization accounts) to Terms of Service
- Renumber all subsequent ToS sections and update cross-references

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@holkexyz
holkexyz merged commit a6519ad into main Apr 2, 2026
3 checks passed
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