Rendering images in Next.js with next-sanity
Reference for the Image component and imageLoader exported from next-sanity/image. Wraps next/image with a Sanity CDN-aware loader.
The next-sanity library exports an Image component and imageLoader function that integrate Sanity's image CDN with the Next.js next/image component. Pass a Sanity CDN URL as the src prop and the component handles format negotiation, responsive sizing, and aspect ratio preservation automatically.
This API is currently in alpha and may change in future releases.
Installation
The Image component and imageLoader require next-sanity 8.3.0 or later. The current major version, next-sanity 13, requires Next.js 16, React 19.2.3 or later, and sanity 5.29.0 or later.
If you don’t already have them, install next-sanity and @sanity/image-url.
npm install next-sanity @sanity/image-urlpnpm add next-sanity @sanity/image-urlyarn add next-sanity @sanity/image-urlbun add next-sanity @sanity/image-urlBasic usage
The Image component accepts a Sanity CDN URL string as its src prop. Use @sanity/image-url to build the URL from your image data (see Build the source URL), then pass it to Image:
import type { SanityImageSource } from '@sanity/image-url'
import { Image } from 'next-sanity/image'
import { urlFor } from '@/sanity/lib/image'
export function AuthorPhoto({ image }: { image: SanityImageSource }) {
return (
<Image
src={urlFor(image).url()}
alt="Author photo"
width={400}
height={300}
/>
)
}How this differs from the next/image component
The Image component from next-sanity/image wraps next/image, so you get the same developer-facing features: lazy loading, srcSet generation, preloading, and layout stability. The difference is in where and how image optimization happens.
With the next-sanity/image component, the built-in loader bypasses the Next.js optimization proxy entirely. Instead, it constructs a URL that points directly to Sanity's image CDN with the right transformation parameters. Sanity's CDN handles resizing, format conversion, and caching at the edge. This means:
- No
remotePatternsconfiguration is needed innext.config.jsfor Sanity images. - Format negotiation (WebP, AVIF) happens at the CDN level through the
auto=formatparameter, based on the browser'sAcceptheader. - Your Next.js server doesn't process the images, reducing its CPU and memory load.
- The loader automatically maintains aspect ratio across
srcSetbreakpoints by recalculating thehparameter proportionally for each width. - The loader sets sensible defaults for the
fitparameter:fit=maxwhen only width is specified (prevents upscaling),fit=minwhen both width and height are present.
There are a couple of tradeoffs. The Image component restricts src to a string (it must be a valid Sanity CDN URL), while next/image also accepts static imports. It also disallows the loader prop since it ships with its own. If you need a custom loader or want to use the default Next.js optimization proxy, use next/image directly.
How the loader works
The built-in imageLoader transforms the Sanity CDN URL for each entry in the generated srcSet. For every width that next/image requests, the loader:
- Sets
auto=formatso the CDN returns the best format the browser supports (WebP, AVIF). See Image transformations for the full list of URL parameters. - Sets
fit=maxwhen only width is specified, orfit=minwhen both width and height are present. If the URL already contains afitparameter, the loader respects it. - Recalculates
hproportionally when bothwandhare present, preserving the original aspect ratio at each breakpoint. - Passes the
qualityprop through as theqURL parameter.
This means your images are served in the optimal format and size without additional configuration.
Props
ImageProps extends all next/image props except loader and changes src to accept only a string.
Requiredsrc
string
A valid Sanity image CDN URL. Build this with
@sanity/image-urlor construct it manually. Ifsrcisn't a valid absolute URL, the component throws aTypeError:The `src` prop must be a valid URL to an image on the Sanity Image CDN.width
number
Width in pixels. Appended as
wto the URL and used by the loader for aspect ratio calculations.height
number
Height in pixels. Appended as
hto the URL and used by the loader for aspect ratio calculations.quality
number
Image quality (0-100). Passed through as
qto the Sanity CDN.loader
never
Not supported. If you pass a custom loader, the component throws a
TypeError:The `loader` prop is not supported on `Image` components. Use `next/image` directly to use a custom loader.
All other next/image props, such as alt, preload, fill, sizes, placeholder, and className, are passed through to the underlying next/image component.
Use the image loader with the next/image component
If you need more control over the next/image component but still want Sanity CDN URL handling, you can use the exported imageLoader directly with next/image:
import type { SanityImageSource } from '@sanity/image-url'
import NextImage from 'next/image'
import { imageLoader } from 'next-sanity/image'
import { urlFor } from '@/sanity/lib/image'
export function CustomImage({ image }: { image: SanityImageSource }) {
return (
<NextImage
loader={imageLoader}
src={urlFor(image).width(800).height(600).url()}
alt="Product photo"
width={800}
height={600}
sizes="(max-width: 768px) 100vw, 800px"
/>
)
}Unlike the Image component, imageLoader doesn't add the width and height props to the URL. Set both dimensions on the URL builder too, as this example does with .width(800).height(600), so the loader can recalculate h and keep the aspect ratio at each srcSet width. Use this approach when you want to wrap imageLoader in your own loader function, for example to add URL parameters. Because the loader prop takes a function, define a custom wrapper loader in a file that starts with 'use client'.
Build the source URL
The Image component expects a Sanity CDN URL string, not a Sanity image reference object. Use @sanity/image-url to build it. See Presenting images for full setup instructions:
// sanity/lib/image.ts
import { createImageUrlBuilder, type SanityImageSource } from '@sanity/image-url'
import { client } from './client'
const builder = createImageUrlBuilder(client)
export function urlFor(source: SanityImageSource) {
return builder.image(source)
}The URL builder respects crop and hotspot settings when you pass the full image object (not just the asset reference). The hotspot is applied only when you set both width() and height() on the builder. You can chain additional transformations before calling .url():
// Crop and hotspot are applied automatically
<Image
src={urlFor(post.mainImage).width(1200).height(675).url()}
alt={post.mainImage.alt || ''}
width={1200}
height={675}
preload
/>Relationship to the @sanity/image-url package
These two tools serve different purposes and work together:
@sanity/image-urlbuilds a Sanity CDN URL string from image data. It handles crop, hotspot, and transformation parameters.next-sanity/imagetakes that URL string and integrates it withnext/imageso you get automaticsrcSetgeneration, format negotiation, and responsive loading from the Sanity CDN.
You can use @sanity/image-url without next-sanity/image (for example, with a plain <img> tag or a different framework's image component). But when using Next.js, the Image component from next-sanity/image gives you the best of both: Sanity CDN transformations with next/image optimizations.
Related resources
- Presenting images: configuring
@sanity/image-url, crop and hotspot, responsive images, and performance tips. - Image transformations: full reference for Sanity CDN URL parameters (
w,h,fit,auto,q, and more). - Image metadata: LQIP placeholders, dimensions, palette, and other metadata available for Sanity images.
- Image schema type: schema configuration for image fields, including crop and hotspot options.
Was this page helpful?
Feedback submitted, thanks for helping us improve the docs. Have you tried these alternatives?