Author image not displaying in Sanity blog post query

11 replies
Last updated: Apr 24, 2023
Hey everyone, can anyone help me solve this issue?
*DESIRED RESULT*: I want the author’s photo to be displayed with each blog article. (Example image attached)

*ISSUE*: The author’s image is not displaying.


Here is my blog page schema:
const blogMain = {
    name: 'post',
    title: 'Post',
    type: 'document',
    fields: [
      {
        name: 'title',
        title: 'Title',
        type: 'string',
      },
      {
        name: 'slug',
        title: 'Slug',
        type: 'slug',
        options: {
          source: 'title',
          maxLength: 96,
        },
      },
      {
        name: 'content',
        title: 'Content',
        type: 'array',
        of: [{ type: 'block' }],
      },
      {
        name: 'excerpt',
        title: 'Excerpt',
        type: 'string',
      },
      {
        name: 'coverImage',
        title: 'Cover Image',
        type: 'image',
        options: {
          hotspot: true,
        },
        fields: [
            {
                name: "alt",
                title: "Alt",
                type: "string",
            },
        ],
      },
      {
        name: 'date',
        title: 'Date',
        type: 'datetime',
      },
      {
        name: 'author',
        title: 'Author',
        type: 'reference',
        to: { type: 'author' },
      },
    ],
    preview: {
      select: {
        title: 'title',
        author: 'author.name',
        media: 'coverImage',
      },
      prepare(selection: { author: any }) {
        const { author } = selection
        return { ...selection, subtitle: author && `by ${author}` }
      },
    },
  }

  export default blogMain

And here is my GROQ:
export async function getPosts(): Promise<Post[]> {
    return createClient(clientConfig).fetch(
        groq`*[_type == "post"]{
            _id,
            _createdAt,
            title,
            "slug": slug.current,
            alt,
            excerpt,
            "coverImage": coverImage.asset->url,
            date,
            "author": author->{name, picture},
        }`
    );
}

Here’s my component in Next:
const BlogPosts = async () => {
    const posts = await getPosts();
    const displayPosts = posts.map((post) => {
        return (
            <div className="max-w-sm rounded overflow-hidden shadow-lg">
                <Link
                    href={`/posts/${post.slug}`}
                    key={post._id}
                >
                    {post.coverImage && (
                        <Image
                            src={post.coverImage}
                            alt={post.title}
                            width={750}
                            height={300}
                            className="object-cover rounded-lg border border-gray-500"
                        />
                    )}
                    <div className="px-6 py-4">
                        <div className="font-bold text-xl mb-2">
                            {post.title}
                        </div>
                        <Image
                            src={post.author.picture}
                            alt="something"
                            width={50}
                            height={50}
                            className="object-cover rounded-lg border border-gray-500"
                        />
                        <div className="font-bold text-sm mb-2">
                            {post.author.name}
                            {post.date}
                        </div>
                        <p className="text-gray-700 text-base">
                            {post.excerpt}
                        </p>
                    </div>
                </Link>
            </div>
        );
    });

    return <div>{displayPosts}</div>;
}

export default BlogPosts;

AI Update

Looking at your code, the issue is that you're querying author->{name, picture} but picture is likely an image object that needs to be expanded to get its URL, just like you did with coverImage.

Your GROQ query needs to expand the author's picture asset reference to get the actual image URL:

export async function getPosts(): Promise<Post[]> {
    return createClient(clientConfig).fetch(
        groq`*[_type == "post"]{
            _id,
            _createdAt,
            title,
            "slug": slug.current,
            alt,
            excerpt,
            "coverImage": coverImage.asset->url,
            date,
            "author": author->{
                name, 
                "picture": picture.asset->url
            },
        }`
    );
}

The key change is "picture": picture.asset->url inside the author projection. This follows the same pattern you're already using for coverImage - you need to dereference the asset with -> and get its url property.

In Sanity, image fields store a reference to an asset document, not the URL directly. The asset->url syntax:

  • asset - accesses the asset reference in the image object
  • -> - dereferences/follows that reference to the actual asset document
  • url - grabs the URL property from that asset document

This is a common gotcha when working with nested references in GROQ! Your schema and component code look fine - it was just the query that needed the fix.

Show original thread
11 replies
inspecting the html in chrome what does the src= value have? when console logging the post what is the value for coverImage?
Hi Parker,chrome devtools shows:

<img alt="something" width="50" height="50" decoding="async" data-nimg="1" class="object-cover rounded-lg border border-gray-500" src="" style="">
Looks like it’s going straight the alt..

Console.log:

<https://cdn.sanity.io/images/ta7lvil7/production/10f3521c92769c03c200b311aeecc3814e0b7f66-1280x720.jpg>
Warning: Each child in a list should have a unique "key" prop.

Check the top-level render call using <div>. See <https://reactjs.org/link/warning-keys> for more information.
    at div
sorry I pasted the wrong source, please check again if you have previously
I’m learning typescript on this project as well, is this a typescript issue?
Here’s my Types file:
When I log the author image, I’m getting the object back:
AUTHOR IMAGE:  {
  crop: { top: 0, left: 0, bottom: 0, _type: 'sanity.imageCrop', right: 0 },
  hotspot: { x: 0.5, y: 0.5, height: 1, _type: 'sanity.imageHotspot', width: 1 },
  _type: 'image',
  asset: {
    _ref: 'image-efbbe065b6589bd853935500e85084e4566cf5e4-512x512-png',
    _type: 'reference'
  }
}
You’ll need to expand the author’s image’s asset or pass the asset to a configured imageUrl builder function. Expanding the asset would look like this:
author->{
  name, 
  picture{
   ...,
   'url': asset->url
  }
}
Thanks RD. That’s good to know and thanks for your help. I wound up using the imageUrl builder but needed to use the createClient from @sanity/client as well. Is this the standard practice?
const builder = imageUrlBuilder(createClient({
        projectId: "abcd1234",
        dataset: "production",
      }));
Yep, that will work! You can also just reuse the client you’ve already configured for your project if you have one.
Thank you very much.
You’re welcome!

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?