This page will focus entirely on the Image schema type we added to our Blog Post, and dissecting the contents via GROQ and Vision. We won't be actually changing anything within our code, but seeing how Images work as references.
Type the following query into Vision:
*[_type == "blogPost"][0] { title, coverImage}
We get a result like this. It contains the hotspot and crop data, the description, and an asset reference. This is what we're going to be focusing on.
{…} 2 properties coverImage:{…} 5 properties _type:image asset:{…} 2 properties _ref:image-43ba15a0ac5cdb288981a5e0d7a4430c4f546035-1920x1080-png _type:reference crop:{…} 5 properties _type:sanity.imageCrop bottom:0 left:0 right:0 top:0 description:This image shows a fictional conversation between an excited blog post author and his unexcited friend. hotspot:{…} 5 properties _type:sanity.imageHotspot height:0.4183464778690211 width:0.3637961335676624 x:0.7337434094903321 y:0.32800567893976423 title:This is my first blog post! Can't you believe it??
Now, lets focus in on our asset reference. As you remember, we can use -> to get the field of a reference. But how do we know what fields are actually there? Sure, we could look at the Reference Documentation, but we want to understand what actually we're referencing with this asset reference.
With the following query, we can display all the fields of the asset reference:
*[_type == "blogPost"][0] { title, "coverImage":coverImage.asset-> { ... }}
And we get a LOT of data from this. Using {}, we're able to open the asset and get several references, for which we chose ... which is all of the fields. Since there's so much, we'll focus on a bit at a time:
{…} 2 properties coverImage:{…} 15 properties _createdAt:2023-02-18T05:19:19Z _id:image-43ba15a0ac5cdb288981a5e0d7a4430c4f546035-1920x1080-png _rev:s8ZXXonkjzNLZspqnDfCSl _type:sanity.imageAsset _updatedAt:2023-02-18T05:19:19Z assetId:43ba15a0ac5cdb288981a5e0d7a4430c4f546035 extension:png metadata:{…} 7 properties mimeType:image/png originalFilename:blog post cover.png path:images/ubthchl0/production/43ba15a0ac5cdb288981a5e0d7a4430c4f546035-1920x1080.png sha1hash:43ba15a0ac5cdb288981a5e0d7a4430c4f546035 size:54847 uploadId:1y6u52y5SkZXOQRgEhMXyZkNvOcIx4nP url:https://cdn.sanity.io/images/ubthchl0/production/43ba15a0ac5cdb288981a5e0d7a4430c4f546035-1920x1080.png title:This is my first blog post! Can't you believe it??
Let's start with everything except the metadata field. You can notice that there's a lot here, including:
- The creation and updated dates of the asset
- The extension of the asset (in this case, png)
- The MIME type (what kind of media it is)
- The file size
- The original file name
- The URL - This is what we were getting when we used coverImage.asset->url
- A bunch of related identification
The same applies to File assets as well - it's with the metadata where things change.
Let's run the following query to only see the metadata:
*[_type == "blogPost"][0] { title, "coverImageMetadata":coverImage.asset->metadata}
Which gives us this result:
{…} 2 properties coverImageMetadata:{…} 7 properties _type:sanity.imageMetadata blurHash:MXQ]~SoH-m%L%0Ixt7t3axs,~SogM~RjNH dimensions:{…} 4 properties _type:sanity.imageDimensions aspectRatio:1.7777777777777777 height:1080 width:1920 hasAlpha:true isOpaque:true lqip:..... palette:{…} 8 properties _type:sanity.imagePalette darkMuted:{…} 5 properties _type:sanity.imagePaletteSwatch background:#212121 foreground:#fff population:0.74 title:#fff darkVibrant:{…} 5 properties _type:sanity.imagePaletteSwatch background:#184cb8 foreground:#fff population:0.01 title:#fff dominant:{…} 5 properties _type:sanity.imagePaletteSwatch background:#047cfb foreground:#fff population:3.89 title:#fff lightMuted:{…} 5 properties _type:sanity.imagePaletteSwatch background:#bcc3ca foreground:#000 population:0.62 title:#fff lightVibrant:{…} 5 properties _type:sanity.imagePaletteSwatch background:#4cc8fc foreground:#000 population:0.01 title:#fff muted:{…} 5 properties _type:sanity.imagePaletteSwatch background:#747474 foreground:#fff population:0.05 title:#fff vibrant:{…} 5 properties _type:sanity.imagePaletteSwatch background:#047cfb foreground:#fff population:3.89 title:#fff title:This is my first blog post! Can't you believe it??
Let's break this up into a few sections.
Dimensions and Information
We get a lot of important information from the metadata, not limited to:
- The height, width, and ratio of the image
- Whether the image is opaque or has alpha channel (used or unused)
- LQIP - a low-quality image preview in the Base64 format
- Blur Hash - an advanced image preview that's more concise
The dimensions are really helpful, especially in the future when we'll talk about using Next.js Image Optimization with Sanity.
Palette
This is one of the coolest parts about the Image Metadata. When you upload an Image, Sanity derives color data related to the image, letting you create entire color schemes based on an image.
We have seven different color options:
- Dark Muted
- Dark Vibrant
- Dominant
- Light Muted
- Light Vibrant
- Muted
- Vibrant
You can pick and choose which you want, and create some really personalized interfaces. Even better, it does a lot of the work around text contrast if you want to put text on top of it. Let's look at the dominant color:
...,dominant:{…} 5 properties _type:sanity.imagePaletteSwatch background:#047cfb foreground:#fff population:3.89 title:#fff...,
In each color, we get a background and foreground color to use together, the population of the color in the image, and a title color.
For example, the following image gives off these colors:

This shows how much you can do with a single image asset, and how powerful these references are. Sanity's Image Transformation system takes it to a whole other level, but we'll talk about that later on.