Handling Images

Plan: Composable Developer

Lesson 15 of 19 · 30 min

Catalyst implements a few specialized components and helpers to simplify working with images from the BigCommerce CDN.

A typical example of a BigCommerce CDN image URL looks like the following:

https://cdn11.bigcommerce.com/s-{store-hash}/images/stencil/256w/image.png

The “256w” segment in the above is a sizing string; the CDN supports dynamic resizing of images by customizing this segment. Image URLs provided in GraphQL Storefront API data (such as product images or the store logo) can be fetched at a specific size by passing an argument into the url field of the appropriate entity.

Catalyst implements a custom image component that supports CDN URLs like the above, or URLs containing a placeholder instead of an explicit size:

https://cdn11.bigcommerce.com/s-{store-hash}/images/stencil/{:size}/image.png

A placeholder image URL like this offers the advantage of deferring sizing consideration to rendering logic, where Next.js’s own image handling capabilities can be incorporated for its automatic handling of layout optimization and responsive srcset generation.

The Catalyst Image component is meant for use with BigCommerce CDN URLs:

import { Image } from '~/components/image';
...
<Image
src={obj.image.urlTemplate}
width={500}
height={500}
/>

This component uses the Next.js Image component under the hood, combined with a custom loader that intelligently incorporates a given size into the given CDN URL.

This means that, when using Next.js’s built-in sizing strategies, appropriate CDN URLs can be generated for any sizes that Next.js requests.

<Image
src={obj.image.urlTemplate}
width={500}
height={500}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>

From the sizes prop above, Next.js will decide what specific sizes to incorporate into srcset, and each will end up with an appropriate BigCommerce CDN URL.

Learn more about the full features of Next.js image handling in the documentation.

CDN URL Sources

The source URL actually provided to Image might originate in one of the following ways:

SourceScenarioUsage
GraphQL DataThe most common way in which CDN URLs are provided. Various GraphQL entities, including products and categories, support querying image details, with CDN URLs being returned.Querying url on the image field of the appropriate entity can be done with a size argument, resulting in a full CDN URL. The urlTemplate field can be queried instead to fetch a URL value containing the "{:size}" placeholder.Provide either of these fields to src on Image.
WebDAVImages you have uploaded to the content directory in your store’s WebDAV.Use the contentImageUrl function with the relative path to generate a CDN URL. The function supports a size argument but will incorporate the "{:size}" placeholder by default.
Image ManagerImages that have been uploaded using the Image Manager in the BigCommerce control panel.Use the imageManagerImageUrl function with the relative path to generate a CDN URL. The function supports a size argument but will incorporate the "{:size}" placeholder by default.

You may notice that in several areas of the default codebase, the Image component seems to be used with the url field of the GraphQL source data:

<Image
src={logo.image.url}
/>

In most cases, the GraphQL queries in question have actually aliased urlTemplate as url, meaning full support for dynamic resizing is actually preserved:

... on StoreImageLogo {
image {
url: urlTemplate
}
}

WebDav and Image Manager examples:

import { contentImageUrl, imageManagerImageUrl } from '~/lib/store-assets';
import { Image } from '~/components/image';
...
{/* Loads a WebDAV content image with dynamic srcset support */}
<Image src={contentImageUrl("myimage.png")} width={500} />
{/* Loads an Image Manager image, but all loaded URLs will use "500w" size */}
<Image src={imageManagerImageUrl("myimage.png", "500w")} width={500} />

WebDAV can be used to host more than just images. CDN URLs for other types of assets can be generated with contentAssetUrl.

<Link href={contentAssetUrl('pdfs/user-manual.pdf')}>
User Manual
</Link>

Resources