Adding images to the blockContent schema in Sanity.io

30 replies
Last updated: Apr 4, 2023
Hello, I have a question about the blockContent-schema + PortableText/React plugin. I build small sites for small businesses, often creative people who wants to custom their’ content a lot. As of now I use the portable text module as often as I can, as they can add/remove content as they wish, without me having to edit the studio. A little like other cmses like hubspot where the rich text-module allows the client to add pretty much anything.BUT, I’m wondering about images. Is there any addon or alternative to the blockContent that allows for the user to add images? Or can you add some functionality to the blockContent so they can add images into it? Thanks in advance!
☀️
AI Update

Yes! You can absolutely add images to Portable Text (block content) in Sanity. Images are one of the most common custom blocks people add, and it's actually quite straightforward to set up.

Adding Images to Block Content

To enable images in your Portable Text schema, you need to add the image type to the of array in your block content field. Here's how:

import { defineType, defineField } from 'sanity'

export default defineType({
  name: 'myDocument',
  type: 'document',
  fields: [
    defineField({
      name: 'content',
      type: 'array',
      of: [
        {
          type: 'block' // Standard rich text
        },
        {
          type: 'image', // This adds image blocks!
          fields: [
            {
              name: 'alt',
              type: 'string',
              title: 'Alternative text',
              description: 'Important for SEO and accessibility',
              options: {
                isHighlighted: true // Shows the field prominently
              }
            },
            {
              name: 'caption',
              type: 'string',
              title: 'Caption'
            }
          ]
        }
      ]
    })
  ]
})

What This Gives Your Clients

Once you add this, your clients will see an image icon in the Portable Text toolbar. They can click it to upload images directly into their content, just like they would in other rich text editors. The images appear as blocks within the content flow, and clients can add alt text and captions right there.

Rendering Images on the Frontend

When you query this content, you'll need to handle the image blocks in your frontend. Here's an example using React with @portabletext/react:

import { PortableText } from '@portabletext/react'
import { urlForImage } from '@/lib/sanity.image'
import Image from 'next/image'

const components = {
  types: {
    image: ({value}) => {
      const imageUrl = urlForImage(value.asset).url()
      
      return (
        <figure>
          <Image
            src={imageUrl}
            alt={value.alt || 'Image'}
            width={800}
            height={600}
          />
          {value.caption && <figcaption>{value.caption}</figcaption>}
        </figure>
      )
    }
  }
}

export default function MyComponent({ content }) {
  return <PortableText value={content} components={components} />
}

Additional Customization

You can also add:

  • Hotspot/crop data (built into Sanity's image type)
  • Multiple image fields (like thumbnails)
  • Custom validation (file size, dimensions)
  • Image metadata (photographer credits, licensing info)

This approach gives your clients the flexibility to add images wherever they need them in their content, without you having to create specific image fields for every possible location. It's perfect for blog posts, articles, case studies, and any content where images need to flow naturally with text.

For more advanced customization, including custom renderers in the Studio and handling complex image blocks, check out the Sanity guide on customizing Portable Text from schema to React component. It walks through everything from schema setup to frontend rendering with detailed examples!

Hey User, did you check https://www.sanity.io/docs/portable-text-editor-configuration ? there is an image example:

export default {
  name: 'content',
  type: 'array',
  title: 'Content',
  of: [
    {
      type: 'block'
    },
    {
      type: 'image'
    }
  ]
}

rofl. Thank you!!!
Sorry to ask again, but where do I place this snippet?
In your schema file
I’ve added it like this, but the image-icon doesn’t appear
The text editor looks like this in the studio:
looks like it is one level too high up
The blue brackets above contains the type: ‘block’
So I can’t put image in there, can I?
no, it has to go in the content array
are you running the studio locally?
Yeah, for now yrs
yes*
can you please share the top part of your code
just close the
marks
attribute
close = collapse
I just tried it on my side and it worked with this code:


export default {
  name: 'chapter',
  type: 'document',
  title: 'Chapter',
  fields: [
    {
      title: 'Title',
      name: 'title',
      type: 'array',
      of: [
        {
          type: 'block',
          styles: [{title: 'Normal', value: 'normal'}],
          lists: [],
          marks: {
            // Only allow these decorators
            decorators: [{title: 'Strong', value: 'strong'}],
            annotations: [],
          },
        },
        {type: 'image'},
      ],
    },
  ],
}

make sure:• to use the latest version of sanity
• that there are no errors on console
• try to add a new content type just for testing / debugging
Hmm, let me update
Now all I get is this error..sigh…
maybe the best would be to create a new project with the latest version and then step by step apply your changes. which version where you on before? 2.x?
I’m not sure. But I started this project by creating a react app, and then installing and initializing Sanity.. I had this problem before too, but then I think I added a sanity.json-file and it worked.
okay, then I would try that again 🙂
So I just added a file, and the studio started, but still no image
And you are 100% sure that
Introtext
uses the content type / schema file you have changed?
to check that, you can change the marks / annotations. If they do not change, then sth is wrong
Uff.. I had added the content in the introtext section to be an array of blocks. So, by changing it to type blockContent fixed it. Thank you!
World record in patience there. 👑
Glad it worked! 🙂
Hey again
user B
, what do you use to render your images? I get “_Unknown block type “image”, specify a component for it in the
components.types
prop_” in the console. I’ve tried a few different ones but can’t seem to make it work

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?