From 82c9626c7571a4651d2d491600fd90531e962d8e Mon Sep 17 00:00:00 2001 From: Rami Bitar Date: Sat, 8 Aug 2026 17:48:19 -0400 Subject: [PATCH] Render Shopify imagery through next/image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turn the optimizer back on by dropping images.unoptimized, and widen the Shopify remote pattern to **.shopify.com so any image subdomain resolves. With the optimizer live, remotePatterns is now actually enforced. Convert the seven Shopify CDN call sites: the product/collection cards and the gallery carousel size with fill + sizes, while the cart, order and search thumbnails carry explicit dimensions. The avatar, markdown, attachment, assistant and logo images stay plain — they take blob:/data: or arbitrary hosts that next/image cannot process. The lightbox needs w-auto h-auto: the width and height attributes next/image requires make both axes definite, so max-w/max-h clamp them independently instead of preserving the ratio. object-contain masked that, but the stretched element covered the overlay and ate the backdrop clicks that close the dialog. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_015uSQQNWrmiYDRW9L9VnsGC --- components/shopify/cart-drawer.tsx | 5 ++- components/shopify/collection-card.tsx | 7 ++-- components/shopify/order-history.tsx | 5 ++- components/shopify/product-card.tsx | 7 ++-- .../product-detail/product-detail-gallery.tsx | 22 ++++++++++--- components/shopify/search-dialog.tsx | 5 ++- next.config.js | 32 +++++++++---------- 7 files changed, 56 insertions(+), 27 deletions(-) diff --git a/components/shopify/cart-drawer.tsx b/components/shopify/cart-drawer.tsx index c8f7c63..ce98e4e 100644 --- a/components/shopify/cart-drawer.tsx +++ b/components/shopify/cart-drawer.tsx @@ -1,6 +1,7 @@ 'use client'; import React, { useState } from 'react'; +import Image from 'next/image'; import { useCartStore, redirectToCheckout } from '@/hooks/use-shopify-cart'; import { Button } from '@/components/ui/button'; import { Loader } from '@/components/ui/loader'; @@ -171,9 +172,11 @@ const CartDrawer: React.FC = () => { {/* Product Image */}
{image ? ( - {item.merchandise.product.title} ) : ( diff --git a/components/shopify/collection-card.tsx b/components/shopify/collection-card.tsx index 2c8e286..cf33a1b 100644 --- a/components/shopify/collection-card.tsx +++ b/components/shopify/collection-card.tsx @@ -1,5 +1,6 @@ import React from 'react'; import Link from 'next/link'; +import Image from 'next/image'; interface CollectionImage { url: string; @@ -27,10 +28,12 @@ const CollectionCard: React.FC = ({ collection }) => { {/* Collection Image */}
{collection.image ? ( - {collection.image.altText ) : (
diff --git a/components/shopify/order-history.tsx b/components/shopify/order-history.tsx index 8f3f5d6..62831f4 100644 --- a/components/shopify/order-history.tsx +++ b/components/shopify/order-history.tsx @@ -1,6 +1,7 @@ 'use client'; import React, { useState } from 'react'; +import Image from 'next/image'; import { RiImageLine } from '@remixicon/react'; import type { Customer, CustomerOrder } from '@/services/shopify/customer'; @@ -123,9 +124,11 @@ const OrderHistory: React.FC = ({ customer }) => {
  • {node.variant?.image ? ( - {node.variant.image.altText ) : ( diff --git a/components/shopify/product-card.tsx b/components/shopify/product-card.tsx index 8818961..bb06cb5 100644 --- a/components/shopify/product-card.tsx +++ b/components/shopify/product-card.tsx @@ -1,5 +1,6 @@ import React from 'react'; import Link from 'next/link'; +import Image from 'next/image'; import { truncate } from '@/lib/utils'; interface ProductImage { @@ -68,10 +69,12 @@ const ProductCard: React.FC = ({ product }) => { {/* Product Image */}
    {firstImage ? ( - {firstImage.altText ) : (
    diff --git a/components/shopify/product-detail/product-detail-gallery.tsx b/components/shopify/product-detail/product-detail-gallery.tsx index eb50adb..d1f671f 100644 --- a/components/shopify/product-detail/product-detail-gallery.tsx +++ b/components/shopify/product-detail/product-detail-gallery.tsx @@ -1,12 +1,15 @@ 'use client'; import React, { useCallback, useEffect, useRef, useState } from 'react'; +import Image from 'next/image'; import { RiCloseLine } from '@remixicon/react'; import { Button } from '@/components/ui/button'; interface ProductImage { url: string; altText?: string | null; + width?: number | null; + height?: number | null; } interface ProductDetailGalleryProps { @@ -136,11 +139,14 @@ const ProductDetailGallery: React.FC = ({ isSingle ? 'sm:col-span-2' : '' }`} > - {image.altText ))} @@ -173,11 +179,19 @@ const ProductDetailGallery: React.FC = ({ onClick={close} className="fixed inset-0 z-100 flex items-center justify-center bg-foreground/20 backdrop-blur-md p-6 md:p-10" > - {zoomedImage.altText event.stopPropagation()} - className="max-h-full max-w-full object-contain" + // w/h-auto keeps the box at the image's own ratio; without it the + // width+height attributes make both axes definite and the element + // stretches to the overlay, swallowing backdrop clicks that close it. + className="max-h-full max-w-full w-auto h-auto object-contain" />