Skip to content

Conversation

@Vaibhav91one
Copy link

@Vaibhav91one Vaibhav91one commented Oct 30, 2025

Summary

This PR replaces standard <img> tags with Next.js's <Image> component across the application to leverage automatic image optimization and improve performance.

Changes Made

  • src/components/footer-pill.tsx - Converted Dodo logo to Next.js Image
  • src/components/header.tsx - Converted business banner and logo to Next.js Image
  • src/components/product/ProductCard.tsx - Converted product images to Next.js Image

Technical Details

  • Uses fill prop for container-bound images
  • Sets priority for above-the-fold banner images
  • Implements placeholder="blur" with appropriate blurDataURL
  • Proper sizes attribute for responsive behavior
  • Fallback to default images where appropriate

Closes #30

Summary by CodeRabbit

  • Chores

    • Optimized image loading across header, footer, and product cards: progressive blur placeholders, responsive sizing, prioritized loading and fallbacks for more consistent and faster image display.
  • New Features

    • Expanded UI text variants: added additional labels and CTAs (trial wording, alternate "Buy now"/"Purchase" texts, and powered-by/logo alt text) to improve clarity and localization.

@coderabbitai
Copy link

coderabbitai bot commented Oct 30, 2025

Walkthrough

Replaced native <img> tags with Next.js Image across header, footer-pill, and product card; added placeholder="blur", blurDataURL, sizes/priority, and image error fallback logic; expanded Business interface in header; updated lingo meta.json with new UI text entries. No public component signatures changed except Business shape.

Changes

Cohort / File(s) Summary
Image component updates
src/components/footer-pill.tsx, src/components/header.tsx, src/components/product/ProductCard.tsx
Replaced native <img> with next/image's Image; added placeholder="blur", blurDataURL, responsive sizes, fill/dimensions, and priority where used; removed prior eslint disables for img usage. ProductCard adds local fallback, imgSrc state, and onError handling to swap sources.
Header public model change
src/components/header.tsx
Extended exported Business interface: added business_id, logo, and name fields while keeping component props usage unchanged.
Localization/meta additions
src/app/lingo/meta.json
Added multiple new text entries and attribute/element nodes for footer, header, and product CTAs (trial text, "Buy now"/"Purchase", logo alt texts, "Powered by Dodo Payments", etc.), expanding mapping paths and variants.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User Agent / Browser
  participant C as Component (Header/Product/Footer)
  participant I as next/Image
  participant S as CDN/Server

  rect rgb(240,248,255)
  C->>I: Render <Image src=... sizes=... placeholder="blur" blurDataURL=... priority? />
  end

  rect rgb(245,255,235)
  I->>U: Show blur placeholder (low-res)
  U-->>I: Request full-res (on viewport/priority)
  I->>S: Fetch optimized asset (WebP/size)
  S-->>I: Return optimized image
  I->>U: Display optimized image
  end

  alt image load error
    U->>C: image load failed
    C->>C: set imgSrc -> fallback
    C->>I: re-render <Image> with fallback src
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Heterogeneous edits: UI components + interface change + localization JSON.
  • Review attention:
    • Verify Business interface consumers match new fields.
    • Confirm blurDataURL values are valid base64 placeholders.
    • Check sizes and priority usage for responsive behavior and accessibility.
    • Ensure fallback image paths exist and onError logic covers SSR/client differences.

Possibly related PRs

  • Refactor #22 — Modifies ProductCard and header business shape; likely overlaps on image/component changes.
  • Lingo update #24 — Edits localization/meta assets similar to the meta.json additions in this PR.

Poem

🐰 I swapped my pics for Image bright,
A tiny blur first greets the sight,
If bits should break I hop to spare,
A fallback waits with gentle care.
Optimized hops — smooth, light, and right! 🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately captures the main change: replacing img tags with Next.js Image component for optimized image loading.
Linked Issues check ✅ Passed The PR successfully implements all acceptance criteria from issue #30, including replacing img tags with Next.js Image across all three specified files, adding lazy loading, blur placeholders, error handling, and proper image configurations.
Out of Scope Changes check ✅ Passed Changes to src/app/lingo/meta.json appear to support the image optimization work by adding UI text mappings for new image-related attributes, which aligns with the component changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 930ebde and 5e71000.

📒 Files selected for processing (3)
  • src/components/footer-pill.tsx (2 hunks)
  • src/components/header.tsx (2 hunks)
  • src/components/product/ProductCard.tsx (2 hunks)

@Amanfromearth
Copy link
Member

@Vaibhav91one Could you rebase with main to resolve the merge conflicts?

@Vaibhav91one Vaibhav91one force-pushed the feature/image-optimization branch from 5e71000 to 23c36c3 Compare November 6, 2025 10:56
@Vaibhav91one
Copy link
Author

Done @Amanfromearth.

@Amanfromearth
Copy link
Member

@Vaibhav91one lingo.dev is translating the blur prop, which is causing an error. To avoid this, can you define:

const IMAGE_PLACEHOLDER = "blur" as const;

and then use:

<Image placeholder={IMAGE_PLACEHOLDER} />

instead of passing "blur" directly?

@Vaibhav91one
Copy link
Author

Hi @Amanfromearth, I have made the changes and also I have made changes that coderabbit requested.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/components/footer-pill.tsx (1)

37-45: Consider using standard <img> for small SVG logos.

The Next.js Image component is now correctly implemented with a proper base64 blurDataURL (past issue resolved). However, for small static SVG logos like this 20×20px brand asset, Next.js Image optimization provides minimal benefit since:

  • SVGs are already optimized vector graphics
  • No format conversion (e.g., WebP) applies to SVGs
  • The optimization overhead may outweigh benefits for such small assets

If you prefer a simpler approach for the SVG logo:

-<Image
-  src="/images/brand-assets/logo/logo.svg"
-  alt="logo"
-  width={20}
-  height={20}
-  className="object-cover object-center"
-  placeholder={IMAGE_PLACEHOLDER}
-  blurDataURL={BLUR_DATA_URL}
-/>
+<img
+  src="/images/brand-assets/logo/logo.svg"
+  alt="logo"
+  width={20}
+  height={20}
+  className="object-cover object-center"
+/>

Note: Given the PR objective explicitly states replacing ALL <img> tags, the current implementation may be intentional. This suggestion is optional.

src/components/header.tsx (1)

32-40: Consider standard <img> for SVG logo (same as footer).

The logo Image component now correctly uses a base64 blurDataURL (past issue resolved). However, similar to the footer logo, using Next.js Image for a 72×72px SVG logo provides minimal optimization benefit since SVGs are already optimized vector graphics.

If you prefer a simpler approach:

-<Image
-  src={business.logo || "/images/brand-assets/logo/logo.svg"}
-  alt="Business Logo"
-  width={72}
-  height={72}
-  className="object-cover object-center"
-  placeholder={IMAGE_PLACEHOLDER}
-  blurDataURL={BLUR_DATA_URL}
-/>
+<img
+  src={business.logo || "/images/brand-assets/logo/logo.svg"}
+  alt="Business Logo"
+  width={72}
+  height={72}
+  className="object-cover object-center"
+/>

Note: This is optional since the current implementation is technically correct and aligns with the PR objective to replace ALL <img> tags.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 23c36c3 and 57c732d.

📒 Files selected for processing (4)
  • src/app/lingo/meta.json (3 hunks)
  • src/components/footer-pill.tsx (2 hunks)
  • src/components/header.tsx (2 hunks)
  • src/components/product/ProductCard.tsx (3 hunks)
🔇 Additional comments (8)
src/components/footer-pill.tsx (1)

7-11: LGTM! Constants approach successfully avoids lingo.dev translation issues.

The implementation correctly follows the recommendation from PR comments to define IMAGE_PLACEHOLDER as a constant rather than passing the string literal "blur" directly, preventing lingo.dev from attempting to translate it. The BLUR_DATA_URL is also properly formatted as a base64-encoded data URL.

Based on PR comments.

src/components/product/ProductCard.tsx (3)

1-13: LGTM! Proper imports and constants defined.

The implementation correctly imports useEffect for prop synchronization and defines appropriate constants for image handling. The constants approach matches the pattern used across other components and prevents lingo.dev translation issues.


57-67: Excellent error handling implementation!

The error handling logic is well-implemented:

  • State management properly tracks the current image source
  • useEffect synchronizes imgSrc when the image prop changes
  • handleImageError uses useCallback for performance and prevents redundant state updates by checking if already on fallback
  • Prevents infinite error loops

This addresses the past review concern about missing error handling.


113-122: LGTM! Image component properly configured.

The Image component implementation correctly addresses all past review concerns:

  • Uses state-managed imgSrc for dynamic fallback handling
  • Proper fill and responsive sizes attributes
  • Valid base64 blurDataURL (past issue resolved)
  • onError handler connected (past issue resolved)
  • No redundant priority={false} prop (past issue resolved)

The implementation meets all acceptance criteria for image optimization with error handling.

src/components/header.tsx (3)

10-12: LGTM! Constants properly defined.

The constants follow the same pattern as other components and prevent lingo.dev translation issues as recommended in PR comments.


18-27: LGTM! Banner image properly optimized.

The banner Image component is correctly configured:

  • Proper base64 blurDataURL (past issue resolved)
  • priority prop correctly set since the banner is above the fold
  • sizes="100vw" appropriate for full-width banner
  • fill for responsive container-bound sizing

1-8: Business interface expansion is compatible with backend changes and requires no additional updates.

The verification confirms all required fields (business_id, logo, name) are already provided by the backend BusinessResponse type. The single consumer of the Business interface is the Header component in src/app/[slug]/page.tsx, which receives the complete data object from getBusiness(). The interface expansion aligns with the backend response structure—no additional changes needed.

src/app/lingo/meta.json (1)

1-465: Translation metadata properly updated.

The lingo metadata file has been updated with new entries corresponding to the Image components' alt text and UI strings added across footer, header, and product components. The JSON structure is valid and changes align with the component updates.

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.

Add Image Optimization with Lazy Loading

2 participants