Issue with rendering Nuxt Sanity images and confusion about data structure and image URL method.

3 replies
Last updated: Aug 28, 2023
im having an issue with nuxt sanity images, they do not render. i see the data coming in i followed the nuxt clean template , but images just dont show up
in the studio i am also geting a weird asset empty
AI Update

I can help you troubleshoot both the image rendering issue in Nuxt and the "asset empty" problem in your Studio. Let me walk you through the most common causes and solutions.

Setting Up Image URL Builder Correctly

The most common issue with Nuxt and Sanity images is that there is no built-in $urlFor helper in @nuxtjs/sanity. You need to create your own image URL builder function using @sanity/image-url.

First, make sure you have the required packages installed:

npm install @nuxtjs/sanity @sanity/image-url

Then create a composable to handle image URLs. Create a file like composables/useSanityImage.ts:

import imageUrlBuilder from '@sanity/image-url'
import type { SanityImageSource } from '@sanity/image-url/lib/types/types'
import { useSanity } from '@nuxtjs/sanity/composables'

export function useSanityImage() {
  const sanityClient = useSanity()
  const builder = imageUrlBuilder(sanityClient.config)
  
  function urlFor(source: SanityImageSource) {
    return builder.image(source)
  }
  
  return { urlFor }
}

Now you can use it in your components:

<script setup>
const query = groq`*[_type == "post"]{
  _id,
  title,
  image
}`

const { data: posts } = await useSanityQuery(query)
const { urlFor } = useSanityImage()
</script>

<template>
  <div v-for="post in posts" :key="post._id">
    <img 
      v-if="post.image?.asset" 
      :src="urlFor(post.image).width(800).url()" 
      :alt="post.title"
    />
  </div>
</template>

Fixing the "Asset Empty" Studio Issue

If you're seeing an empty asset object in the Studio, this usually indicates one of these problems:

1. Image Schema Configuration

Make sure your schema properly defines the image field as type 'image':

defineField({
  name: 'image',
  title: 'Image',
  type: 'image',
  options: {
    hotspot: true // optional but recommended
  }
})

2. Image Upload Failed or Still Processing

Sanity processes image metadata asynchronously after upload. If you just uploaded the image:

  • Wait a few seconds and refresh the Studio
  • Check your browser console for upload errors
  • Try re-uploading the image

3. Delete and Re-upload

If the asset is permanently empty, delete the image field value in your document and upload a fresh image. This usually resolves corrupted references.

Verify Your GROQ Query

Make sure your GROQ query returns the complete image object with its asset reference:

*[_type == "post"]{
  _id,
  title,
  image  // Returns full image object including asset reference
}

A properly uploaded image should return data structured like this:

{
  "_type": "image",
  "asset": {
    "_ref": "image-abc123xyz...",
    "_type": "reference"
  }
}

If the asset object is empty ({}), the image wasn't properly uploaded.

Check Your Nuxt Configuration

Verify your nuxt.config.ts has the correct Sanity configuration:

export default defineNuxtConfig({
  modules: ['@nuxtjs/sanity'],
  sanity: {
    projectId: 'your-project-id',
    dataset: 'production',
    apiVersion: '2024-03-15', // use current date
  },
})

Debugging Steps

Add console logging to see what data you're actually receiving:

<script setup>
const { data: posts } = await useSanityQuery(query)
console.log('Posts data:', posts)
console.log('First image:', posts?.[0]?.image)
console.log('Asset reference:', posts?.[0]?.image?.asset)
</script>

Check if:

  • The asset property exists on your image object
  • The asset._ref or asset._id is present
  • The data structure matches what the image URL builder expects

Quick Troubleshooting Checklist

  • ✅ Schema defines field as type: 'image' (not 'file')
  • ✅ Created your own urlFor function using imageUrlBuilder from @sanity/image-url
  • ✅ GROQ query returns the full image object
  • @nuxtjs/sanity and @sanity/image-url are installed
  • ✅ Sanity config has correct projectId and dataset
  • ✅ Images show a preview thumbnail in Studio (not empty)
  • ✅ Using conditional rendering v-if="image?.asset" to avoid errors
  • ✅ Calling .url() at the end of your image builder chain

The key issue is usually that images won't render without properly setting up the image URL builder yourself - it's not automatically available as a helper in Nuxt. Once you create the useSanityImage composable as shown above, your images should start rendering correctly. The image URL builder gives you access to Sanity's globally-distributed CDN with automatic caching and optimization.

Here is what that data means and here is how you can show an image.
user M
im aware of the field meanings, im just trying to show the data that i have setup.
but, when i see the data come in, its showing me a proxy object for which it doesnt seem to allow me to load the image.

im using this as the jump off
https://github.com/sanity-io/sanity-template-nuxt-clean/
the expectation is that i could create a new document, have an image there (copy paste from the post starter schema) and then i should be able to display it, in theexact same way the starter template does.

i cant understand why the data comes in differnetly or why the image url method doesnt do anything or sil;ently fails
ok
user M
i figured it out, there is some odd transformation hapopening here.
so when you run this


const { data: landing } = await useSanityQuery(query);

it kicks back a proxy obj in the server side, but when you interpolate in the template, you actually calling the getter data.value. so you just interpolate the data.property.

so once i figured that out it makes more sense now. but i have to admit, its not the most straight forward thing to realize when 1st looking at it.

took some time to wrap my min d around it and chekcign the proto of the return groq query

 <img
                    v-if="landing.bigImage._type === 'image'"
                    :src="$urlFor(landing.bigImage).height(1000).width(2000).url()"
                    alt="main-section03.png"
                    class="listings-left-third img-background d-none d-lg-block"
                />

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.

Was this answer helpful?