Next/Image with Sanity CMS

For anybody that’s looking at building Next.js websites with a headless content management system, we have a nice utility for handling images. Ours is specific to Sanity, but with a little prompt from something like Cursor this could very easily be translated to pretty much any headless content management systems. Hell, we might even do it as an article for the free SEO.

Without further ado here’s the code, go steal it:

import { ReactElement } from 'react';
import Image from 'next/image';
import { getImageDimensions } from '@sanity/asset-utils';
import { urlFor } from '~/lib/sanity';

export const IdealImage = ({ image }): ReactElement => {
  const alt = image?.alt ?? "image broke";
  const dimensions = getImageDimensions(image); 
  return (
    <div>
      ...
      {image?.asset && (
        <Image
          src={urlFor(image).url()}
          alt={alt}
          width={dimensions.width}
          height={dimensions.height}
          placeholder="blur"
          blurDataURL={urlFor(image).width(24).height(24).blur(10).url()}
          sizes="
            (max-width: 768px) 100vw,
            (max-width: 1200px) 50vw,
            40vw"
        />
      )}
      ...
    </div>
  );
};

If you want to have a deeper dive as to why we’ve used the sizes that we’ve used, you can read the full article here.

Some cliffnotes -

  • We use the sizes because our image goes from full width, to half width, to slightly less than half width on larger desktop
  • There’s some space to use blurHash and lqip but we kept it simple so most folks can cut and paste this in and it would work. Read more for this here
  • There are image libraries such as this one, but we just like Next/Image for the vibes, so we use that
  • You also need the {image?.asset && ( or else the image will break in preview if you haven’t set an image source.
3 Likes

And can even add fill as a boolean in the props, many possibilities :saluting_face:

2 Likes

Oh, I didn’t know the urlFor(image) would return a base64 for the blurDataUrl field. That’s very handy!

One other thing is to make sure that you call the imageBuilder in the right place, like a RSC statically rendered or get the result in cache, this way it only gets called once, and this way you avoid spiking your Sanity bandwidth allocation.

3 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.