fix: make container widths responsive for consistent large-screen alignment - #32
Conversation
…-360 Replace fixed max-w-360 (1440px) with responsive breakpoints: - lg:max-w-7xl (1280px) at 1024px+ - 2xl:max-w-360 (1440px) at 1536px+ This ensures consistent alignment across all sections at varying zoom levels.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThis PR updates responsive layout classes across marketing sections, refines the testimonials carousel behavior and card sizing, and wires email OTP support through auth, email sending, and the login/signup forms. ChangesMarketing container and testimonials updates
Auth plugin wiring and OTP flow
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@src/features/marketing/components/course-detail-content-section.tsx`:
- Line 319: The layout in course-detail-content-section’s main wrapper can
overflow at lg because the fixed grid columns are wider than the available
content area with lg padding. Update the grid definition on the wrapper so one
track becomes flexible or bounded (for example, keep the main content fluid and
constrain the sidebar), or shift the larger horizontal padding to a wider
breakpoint. Focus on the flex/grid container in CourseDetailContentSection that
currently uses the two fixed column sizes.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: fd0a8996-12c6-410c-afff-de7a87cbea9c
📒 Files selected for processing (18)
src/features/marketing/components/about-ai-healthcare-section.tsxsrc/features/marketing/components/about-hero-section.tsxsrc/features/marketing/components/about-our-values-section.tsxsrc/features/marketing/components/contact-hero-section.tsxsrc/features/marketing/components/course-detail-content-section.tsxsrc/features/marketing/components/course-detail-hero-section.tsxsrc/features/marketing/components/courses-hero-section.tsxsrc/features/marketing/components/cta-section.tsxsrc/features/marketing/components/donation-cta-section.tsxsrc/features/marketing/components/donation-hero-section.tsxsrc/features/marketing/components/donation-support-section.tsxsrc/features/marketing/components/faq.tsxsrc/features/marketing/components/footer.tsxsrc/features/marketing/components/hero-section.tsxsrc/features/marketing/components/how-can-we-support.tsxsrc/features/marketing/components/mission-sections.tsxsrc/features/marketing/components/navbar.tsxsrc/features/marketing/components/testimonials.tsx
- Make testimonial cards responsive: 3 cards always fit viewport width using calc((100%-60px)/3) on lg+ instead of fixed 330px - Center footer text on mobile via text-center, restore left align on md+ - Add emailOTP plugin to server auth config (client already had it)
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
src/features/marketing/components/testimonials.tsx (1)
96-130: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winConsider updating
sizesto match the responsive card width.Cards now size via
lg:w-[calc((100%-60px)/3)]onlg+, but theImagesizesprop remains hardcoded at"330px"(Line 109). This can causenext/imageto serve a slightly mismatched image variant onlg+viewports where the actual rendered width differs from 330px.♻️ Proposed fix
- sizes="330px" + sizes="(min-width: 1024px) calc((100vw - 60px) / 3), 330px"🤖 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 `@src/features/marketing/components/testimonials.tsx` around lines 96 - 130, The testimonial card image sizing is hardcoded in the Image component while the article width changes responsively in testimonials.tsx. Update the Image sizes prop in the reviews.map render to reflect the lg layout used by the card className on the article, so next/image can pick the correct asset for both mobile and lg+ widths. Use the Image and article elements inside the testimonials component as the reference points.
🤖 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 `@src/features/marketing/components/footer.tsx`:
- Around line 66-71: The newsletter text and signup form are using different
width constraints, which makes the footer section look uneven between lg and xl
breakpoints. Update the paragraph in the footer component to use the same lg
max-width as the form, keeping the layout consistent; adjust the text block near
the newsletter copy in the footer component so it matches the form’s width
behavior.
- Around line 102-104: The `ModernAdvocates` heading in `footer.tsx` is still
using a 1280px-based `2xl:-translate-x` offset even though the `2xl:max-w-360`
container grows to 1440px. Update the `p` element’s `2xl` translate calc to use
the 1440px container width, or replace the hardcoded width with a shared layout
token so the heading stays aligned with the widened footer at `2xl`.
In `@src/infrastructure/auth/auth.ts`:
- Line 17: The auth configuration currently enables emailOTP() without the
required server-side delivery callback, so the OTP plugin cannot send codes.
Update the auth setup in auth.ts to pass a sendVerificationOTP handler alongside
emailOTP(), matching the already-registered emailOTPClient() on the client. Use
the existing auth plugin configuration block to wire the handler in with the
same auth instance so OTP delivery works end to end.
---
Nitpick comments:
In `@src/features/marketing/components/testimonials.tsx`:
- Around line 96-130: The testimonial card image sizing is hardcoded in the
Image component while the article width changes responsively in
testimonials.tsx. Update the Image sizes prop in the reviews.map render to
reflect the lg layout used by the card className on the article, so next/image
can pick the correct asset for both mobile and lg+ widths. Use the Image and
article elements inside the testimonials component as the reference points.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: c95c1fb9-b36f-454d-94ab-49578a4f5cdd
📒 Files selected for processing (4)
src/features/marketing/components/course-detail-content-section.tsxsrc/features/marketing/components/footer.tsxsrc/features/marketing/components/testimonials.tsxsrc/infrastructure/auth/auth.ts
✅ Files skipped from review due to trivial changes (1)
- src/features/marketing/components/course-detail-content-section.tsx
| <p className="mt-5 text-sm leading-normal xl:max-w-[387px]"> | ||
| Stay connected and informed: Join our newsletter for the latest | ||
| updates, inspiration, and design insights. | ||
| </p> | ||
|
|
||
| <form className="mt-6 flex w-full max-w-[374px] items-center justify-between rounded-[60px] bg-[#f5f5f5] py-2.5 pr-2.5 pl-5"> | ||
| <form className="mt-6 flex w-full items-center justify-between rounded-[60px] bg-[#f5f5f5] py-2.5 pr-2.5 pl-5 lg:max-w-[374px]"> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the relevant file with line numbers, limited to the component area.
sed -n '1,220p' src/features/marketing/components/footer.tsx
# Find likely parent/layout usage for this footer component.
rg -n "footer" src/features/marketing -g '!**/node_modules/**'Repository: Smartlify07/Modern-Advocates
Length of output: 5155
Align the newsletter copy and form widths. The paragraph stays unconstrained until xl, while the form is capped at lg, so the section can look uneven between 1024–1279px. Cap the paragraph at lg as well.
🤖 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 `@src/features/marketing/components/footer.tsx` around lines 66 - 71, The
newsletter text and signup form are using different width constraints, which
makes the footer section look uneven between lg and xl breakpoints. Update the
paragraph in the footer component to use the same lg max-width as the form,
keeping the layout consistent; adjust the text block near the newsletter copy in
the footer component so it matches the form’s width behavior.
| <p className="pointer-events-none left-1/2 mt-10 translate-x-[20%] bg-gradient-to-b from-ma-text from-[40%] to-ma-text/0 to-[74%] bg-clip-text font-heading text-[40px] leading-none font-extrabold whitespace-nowrap text-transparent select-none lg:absolute lg:top-[370px] lg:left-1/2 lg:-translate-x-[calc(1280px/2-100px)] lg:text-[100px] xl:text-[124px] 2xl:-translate-x-[calc(1280px/2-116px)]"> | ||
| ModernAdvocates | ||
| </p> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== footer slice ==\n'
sed -n '1,220p' src/features/marketing/components/footer.tsx
printf '\n== search max-w-360 ==\n'
rg -n "max-w-360|1280px/2-116px|1440px/2|calc\\(" src -SRepository: Smartlify07/Modern-Advocates
Length of output: 12534
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== footer slice ==\n'
sed -n '1,220p' src/features/marketing/components/footer.tsx
printf '\n== search max-w-360 and related config ==\n'
rg -n "max-w-360|1280px/2-116px|1440px/2|maxWidth|container" -S . --glob '!**/node_modules/**'Repository: Smartlify07/Modern-Advocates
Length of output: 9310
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== tailwind/theme config files ==\n'
fd -a "tailwind*|postcss*|globals.css|theme.*|config.*" .
printf '\n== search for 360 width token ==\n'
rg -n "360|7xl|max-w-360|maxWidth|spacing" -S tailwind.config.* src app . --glob '!**/node_modules/**' --glob '!**/pnpm-lock.yaml'
printf '\n== search for custom maxWidth definitions ==\n'
rg -n "maxWidth:|theme:|extend:" -S . --glob '!**/node_modules/**' --glob '!**/pnpm-lock.yaml'Repository: Smartlify07/Modern-Advocates
Length of output: 27208
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== globals.css theme section ==\n'
sed -n '1,260p' src/app/globals.css
printf '\n== search for max-w-360 token definition ==\n'
rg -n "`@theme`|--container-360|max-w-360|360rem|1440px|1280px" src/app src -S
printf '\n== search for tailwind config files ==\n'
fd -a 'tailwind.config.*|tailwind.*.*|*.config.*' .
printf '\n== search for custom container widths in css ==\n'
rg -n "container|max-width|--container|--breakpoint" src/app src -SRepository: Smartlify07/Modern-Advocates
Length of output: 9325
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n "1280px/2-|1440px/2-|calc\\(1280px/2|calc\\(1440px/2" src -SRepository: Smartlify07/Modern-Advocates
Length of output: 618
🌐 Web query:
Tailwind CSS v4 max-w-360 spacing scale 1440px default 0.25rem
💡 Result:
In Tailwind CSS v4, the spacing system was fundamentally redesigned to move away from a fixed, predefined list of scale values toward a dynamic multiplier-based system [1]. Default Spacing Scale By default, Tailwind CSS v4 defines a single base unit in the CSS @theme block: --spacing: 0.25rem; (which is equivalent to 4px) [1][2][3]. Rather than having a hardcoded list like in v3, v4 utilities are generated dynamically using the formula calc(var(--spacing) * n) [1][2]. This means that virtually any integer or decimal multiple of 0.25 is available as a spacing utility [1]. For example, max-w-360 is valid by default and calculates to 360 * 0.25rem = 90rem (1440px) [1][4]. Key Details: - Dynamic Generation: You can use utilities like max-w-360, p-100, or gap-5.5 because the framework derives these values on the fly from the --spacing variable [1][4]. - Customization: You can change the base unit by overriding the --spacing variable in your @theme block. For example, setting @theme { --spacing: 0.1rem; } would change the multiplier base to 0.1rem, making max-w-360 equal to 36rem [4]. - Compatibility: While v4 is highly dynamic, it maintains support for many standard practices, though explicit legacy spacing configurations are no longer required or used in the same way as v3 [5][1]. In summary, max-w-360 is supported in Tailwind CSS v4 because the framework no longer relies on a restricted list of spacing constants, but instead uses a multiplier system based on the default 0.25rem spacing unit [1][3].
Citations:
- 1: Replace default explicit spacing scale with multiplier system tailwindlabs/tailwindcss#14857
- 2: https://frontend-hero.com/tailwind-spacing
- 3: https://blog.logrocket.com/tailwind-css-guide/
- 4: https://stackoverflow.com/questions/79583168/custom-spacing-values-in-tailwind-css-v4
- 5: Spacing Scale tailwindlabs/tailwindcss.com#2118
Adjust the 2xl heading offset to the 1440px container. In src/features/marketing/components/footer.tsx, 2xl:max-w-360 expands to 1440px, but 2xl:-translate-x-[calc(1280px/2-116px)] still anchors to 1280px. If this text should stay aligned with the widened footer container, switch that calc to the 1440px base or a shared width 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 `@src/features/marketing/components/footer.tsx` around lines 102 - 104, The
`ModernAdvocates` heading in `footer.tsx` is still using a 1280px-based
`2xl:-translate-x` offset even though the `2xl:max-w-360` container grows to
1440px. Update the `p` element’s `2xl` translate calc to use the 1440px
container width, or replace the hardcoded width with a shared layout token so
the heading stays aligned with the widened footer at `2xl`.
… yet), add OTP email sending callback, improve error handling
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/features/marketing/components/mission-sections.tsx (2)
117-117: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winMin-height breakpoint mismatch between the two cards.
Card 1's left content uses
sm:min-h-79.5(line 117, unchanged) while card 2's now usesmd:min-h-79.5(line 155). Between 640px and 768px, card 1 enforces the min-height but card 2 does not, so the two cards can render with mismatched heights in that viewport range.🩹 Suggested fix
- <div className="flex min-w-0 flex-col justify-between gap-2.5 sm:gap-0 md:min-h-79.5"> + <div className="flex min-w-0 flex-col justify-between gap-2.5 sm:min-h-79.5 sm:gap-0">Also applies to: 155-155
🤖 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 `@src/features/marketing/components/mission-sections.tsx` at line 117, The two mission cards use different responsive min-height breakpoints in the shared left-content container, causing mismatched heights between 640px and 768px. Update the breakpoint on the second card’s `div` in `mission-sections.tsx` so it matches the first card’s `sm:min-h-79.5`, keeping the `sm:` behavior consistent across both card sections.
173-184: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
object-covermoved to the non-replaced wrapperdivinstead of theImage.Line 173 adds
object-coveron the outerdiv(shrink-0 overflow-hidden rounded-2xl object-cover ...), butobject-fitonly applies to replaced elements (img/video); on adivit's a no-op. Meanwhile, the actual<Image>at lines 177-180 lostobject-coverand now only hassize-full lg:h-[318px]. Compare with card 1'sImage(line 142) which correctly keepsclassName="size-full object-cover"directly on the element.With explicit width/height forced via the wrapper (
lg:w-[292px]) and the image (lg:h-[318px]), and noobject-fiton theImage, the browser default (object-fit: fill) will stretch/figma-home/support.pngif its intrinsic aspect ratio doesn't exactly match 292×318, causing visible distortion during the hover transition.🩹 Suggested fix
<div - className={`shrink-0 overflow-hidden rounded-2xl object-cover transition-all duration-500 max-lg:w-full ${ + className={`shrink-0 overflow-hidden rounded-2xl transition-all duration-500 max-lg:w-full ${ hovered === "second" ? "lg:w-[292px]" : "w-0 min-w-0" }`} > <Image src="/figma-home/support.png" alt="" - className="size-full lg:h-[318px]" + className="size-full object-cover lg:h-[318px]" loading="lazy" width={292} height={318} />🤖 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 `@src/features/marketing/components/mission-sections.tsx` around lines 173 - 184, The hover image in mission-sections should apply object-cover to the actual Image component, not the wrapper div, because object-fit is ignored on non-replaced elements. Update the second card’s Image (the one using the support.png asset) to include the same sizing/fit treatment as the first card’s Image, and remove the ineffective object-cover from the outer wrapper so the image doesn’t stretch when the hovered width changes.
🧹 Nitpick comments (1)
src/features/auth/components/signup-form.tsx (1)
73-81: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winInvalid-code feedback regressed to a generic message.
By dropping the explicit
checkVerificationOtpstep, an invalid/expired OTP now falls through tosignIn.emailOtpand only ever surfaces the generic"Failed to sign in. Please try again.", whereas the login form still shows a distinct message viaverifyError.message. Consider surfacingsignInError.messagehere so a bad code is distinguishable from a transient sign-in failure and to keep parity withlogin-form.tsx.♻️ Suggested change for clearer messaging
if (signInError) { - setError("Failed to sign in. Please try again.") + setError(signInError.message ?? "Failed to sign in. Please try again.") return }Please verify that
signIn.emailOtpin better-auth1.6.18returns a user-readablemessagefor an invalid/expired code (vs. an internal error string).🤖 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 `@src/features/auth/components/signup-form.tsx` around lines 73 - 81, The signup flow in signup-form.tsx now hides invalid or expired OTP feedback behind a generic sign-in error. Update the signIn.emailOtp handling in the signup form to surface the returned signInError.message when present, matching the clearer messaging used in login-form.tsx and preserving a distinct invalid-code response from transient sign-in failures.
🤖 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 `@src/infrastructure/email/send.ts`:
- Around line 21-28: The OTP send flow in send should not return res.data
blindly because resend.emails.send can surface API-level failures through
res.error. Update the send logic to destructure { data, error } from
resend.emails.send, use the existing send/email function path to log or throw
when error is present, and only return data when the request succeeds.
- Around line 29-32: The OTP resend flow is not waiting for the email send
promise, so failures can escape as unhandled rejections and never fail the auth
path. Update sendVerificationOTP in auth.ts to await the sendOTPEmail call (or
otherwise return its promise) so errors propagate through the existing try/catch
handling, and keep the send.ts error path aligned with the auth flow. Use the
sendOTPEmail and sendVerificationOTP symbols to locate the async boundary.
---
Outside diff comments:
In `@src/features/marketing/components/mission-sections.tsx`:
- Line 117: The two mission cards use different responsive min-height
breakpoints in the shared left-content container, causing mismatched heights
between 640px and 768px. Update the breakpoint on the second card’s `div` in
`mission-sections.tsx` so it matches the first card’s `sm:min-h-79.5`, keeping
the `sm:` behavior consistent across both card sections.
- Around line 173-184: The hover image in mission-sections should apply
object-cover to the actual Image component, not the wrapper div, because
object-fit is ignored on non-replaced elements. Update the second card’s Image
(the one using the support.png asset) to include the same sizing/fit treatment
as the first card’s Image, and remove the ineffective object-cover from the
outer wrapper so the image doesn’t stretch when the hovered width changes.
---
Nitpick comments:
In `@src/features/auth/components/signup-form.tsx`:
- Around line 73-81: The signup flow in signup-form.tsx now hides invalid or
expired OTP feedback behind a generic sign-in error. Update the signIn.emailOtp
handling in the signup form to surface the returned signInError.message when
present, matching the clearer messaging used in login-form.tsx and preserving a
distinct invalid-code response from transient sign-in failures.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 5b26e0df-70c7-44a4-833b-9dc2b6b85e4e
⛔ Files ignored due to path filters (1)
public/figma-home/support.pngis excluded by!**/*.png
📒 Files selected for processing (6)
src/features/auth/components/login-form.tsxsrc/features/auth/components/signup-form.tsxsrc/features/marketing/components/footer.tsxsrc/features/marketing/components/mission-sections.tsxsrc/infrastructure/auth/auth.tssrc/infrastructure/email/send.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- src/infrastructure/auth/auth.ts
- src/features/marketing/components/footer.tsx
| const res = await resend.emails.send({ | ||
| from: "ModernAdvocates <onboarding@resend.dev>", | ||
| to: email, | ||
| subject, | ||
| html: `<p>Your code is: <strong>${otp}</strong></p><p>This code expires in 5 minutes.</p>`, | ||
| }) | ||
|
|
||
| return res.data |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
resend node SDK emails.send return value data error version 6
💡 Result:
In the Resend Node.js SDK (including version 6 and later), the emails.send method does not throw exceptions for API errors [1][2]. Instead, it returns an object containing both data and error properties [1][3]. To correctly handle the response, you must destructure the returned object and explicitly check for the presence of the error property [1][3]. Recommended Pattern: const { data, error } = await resend.emails.send({ from: 'you@example.com', to: 'user@example.com', subject: 'Hello World', html: '
It works!
', }); if (error) { // Handle the error (e.g., log it or return a response) console.error(error); return; } // Success console.log(data); // { id: '...' } Key Points: 1. Return Value Structure: On success, data contains an object with the email ID (e.g., { id: '...' }) and error is null [1][4]. On failure, data is null and error contains details about the failure [1][3]. 2. Avoid Try/Catch for API Errors: Because the SDK returns the error object rather than throwing, a traditional try/catch block will not catch validation or API-level errors [1][2]. Only use try/catch if you need to handle network-level failures or unexpected exceptions outside the SDK's internal error handling [1]. 3. Error Object Shape: While the standard structure is { message: string, name: string }, users have noted that the shape of the error object can sometimes vary or include additional fields like statusCode depending on the specific API response [5]. Always inspect the error object if you need to implement granular logic based on error types [5].Citations:
- 1: https://resend.com/docs/send-with-express
- 2: NodeJS - Errors Not Throwing Thus Avoiding Catch Block of Try Catch resend/resend-node#346
- 3: https://resend.com/docs/send-with-nextjs
- 4: https://resend.com/docs/api-reference/emails
- 5: Inconsistent
ErrorResponsecontents:.errorvs.messageresend/resend-node#538
Handle res.error from resend.emails.send emails.send(...) returns { data, error } for API-level failures, so the current return res.data path can silently drop invalid-recipient/rate-limit/auth errors and make OTP delivery fail without surfacing anything. Destructure the response, log/throw on error, and only return data on success.
🤖 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 `@src/infrastructure/email/send.ts` around lines 21 - 28, The OTP send flow in
send should not return res.data blindly because resend.emails.send can surface
API-level failures through res.error. Update the send logic to destructure {
data, error } from resend.emails.send, use the existing send/email function path
to log or throw when error is present, and only return data when the request
succeeds.
| } catch (error) { | ||
| console.error(error) | ||
| throw error | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
rg -nP -C3 'sendOTPEmail\s*\(' --type=tsRepository: Smartlify07/Modern-Advocates
Length of output: 166
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== files ==\n'
git ls-files 'src/**' | sed -n '1,200p'
printf '\n== search sendOTPEmail / verification callback ==\n'
rg -n -C3 'sendOTPEmail|sendVerificationOTP|verificationOTP|OTPEmail|send.*OTP' src --type=ts || trueRepository: Smartlify07/Modern-Advocates
Length of output: 7604
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== target files ==\n'
fd -a 'auth.ts|send.ts' src
printf '\n== outline candidate files ==\n'
for f in $(fd -a 'auth.ts|send.ts' src); do
echo "--- $f"
ast-grep outline "$f" --view expanded || true
done
printf '\n== relevant snippets ==\n'
for f in $(fd -a 'auth.ts|send.ts' src); do
echo "--- $f"
rg -n -C4 'sendOTPEmail|sendVerificationOTP|async .*send|return .*send|await .*send' "$f" || true
doneRepository: Smartlify07/Modern-Advocates
Length of output: 2322
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== file presence ==\n'
git ls-files 'src/infrastructure/**' | sed -n '1,200p'
printf '\n== direct matches in auth/email files ==\n'
for f in $(git ls-files 'src/infrastructure/**'); do
case "$f" in
*auth.ts|*send.ts)
echo "--- $f"
cat -n "$f" | sed -n '1,220p'
;;
esac
doneRepository: Smartlify07/Modern-Advocates
Length of output: 6839
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== repo files containing auth or email ==\n'
git ls-files | rg '(^|/)(auth|email|send).*\.ts$|/auth/|/email/' || true
printf '\n== broad OTP-related search ==\n'
rg -n -C3 'OTP|verification email|verification.*email|send.*email|await.*email|return.*email' src --type=ts || trueRepository: Smartlify07/Modern-Advocates
Length of output: 7262
Await the OTP send in src/infrastructure/auth/auth.ts. sendVerificationOTP drops the sendOTPEmail promise, so a resend failure never reaches the auth flow and can surface as an unhandled rejection.
Fix
async sendVerificationOTP({ email, otp, type }) {
- sendOTPEmail({ email, otp, type })
+ await sendOTPEmail({ email, otp, type })
}🤖 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 `@src/infrastructure/email/send.ts` around lines 29 - 32, The OTP resend flow
is not waiting for the email send promise, so failures can escape as unhandled
rejections and never fail the auth path. Update sendVerificationOTP in auth.ts
to await the sendOTPEmail call (or otherwise return its promise) so errors
propagate through the existing try/catch handling, and keep the send.ts error
path aligned with the auth flow. Use the sendOTPEmail and sendVerificationOTP
symbols to locate the async boundary.
Summary
All sections used a fixed
max-w-360(1440px) container, which didn't scale properly at different zoom levels. At 80-90% zoom on typical laptops (effective viewport 1024-1279px), sections with different padding breakpoints drifted out of alignment.Fix: Replaced
max-w-360with responsive breakpoints across all 18 marketing section components:lg:max-w-7xl— 1280px max-width at 1024px+2xl:max-w-360— 1440px max-width at 1536px+Also normalized padding breakpoints from
xl:px-25tolg:px-25so all sections get consistent 100px padding from 1024px upward.Files changed: 18 components (navbar, hero, mission sections, testimonials, CTA, footer, course detail, about, contact, donation pages)
Summary by CodeRabbit