Can someone point me to the docs where you return a URL for an image?
You're running into a common point of confusion! When you query image fields in Sanity, you get an asset object with just _ref and _type because that's how Sanity stores references to image assets. The actual url and other properties live in the asset document itself, which you need to either dereference in your GROQ query or build using the @sanity/image-url library.
Two Solutions:
1. Dereference in your GROQ query (Recommended for most cases)
Use the dereference operator -> in GROQ to expand the asset reference and get the URL:
*[_type == "yourDocType"] {
title,
image {
asset-> {
url
}
}
}Or more concisely:
*[_type == "yourDocType"] {
title,
"imageUrl": image.asset->url
}This will give you the direct CDN URL to the image.
2. Use @sanity/image-url (Recommended for frontend rendering)
For most frontend applications, you'll want to use the @sanity/image-url package instead. This gives you much more control over image transformations (sizing, quality, format, etc.):
pnpm add @sanity/image-urlThen create a helper function:
import imageUrlBuilder from '@sanity/image-url'
import { client } from './client'
const builder = imageUrlBuilder(client)
export function urlFor(source) {
return builder.image(source)
}Now you can use it with just the asset reference (no need to dereference in GROQ):
// Your query returns: { image: { asset: { _ref: "...", _type: "reference" } } }
// Build the URL with transformations:
const imageUrl = urlFor(document.image).width(800).url()The image-url builder is the preferred approach because it lets you apply transformations on-the-fly like width, height, quality, format (WebP, AVIF), and automatically handles Sanity's image CDN parameters.
Why you only see _ref and _type
This is by design in Sanity's architecture. When you upload an image, Sanity creates a separate asset document in the Content Lake and stores a reference to it in your document. The reference access operator -> resolves these references by executing an internal subquery to fetch the linked asset data.
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.