How to Attach a Blob of Image to the Editor

5 replies
Last updated: Oct 8, 2020
Hello folks, I'm wondering if it's possible to attach on the editor a blob as an actual image?What I'm thinking of is...

1. On the editor, I put a title and a description
2. There is a button called "Generate og:image"
3. If I click it, it creates a blob of image on the browser
4. It is attached as an actual image
5. It will be uploaded to sanity cdn.
6. During the build time (or on the server) the url is used for 'og:image' tag.

I'm curious about (4). I might need to dig more into sources of image type. But has anyone done something similar already?

https://www.sanity.io/docs/image-type#sources-d82cf03b063c
AI Update

Yes, this is absolutely possible! You're on the right track. Let me walk you through how to upload a browser-generated blob as an actual image asset to Sanity.

The Solution

You can create a custom button or action that:

  1. Generates your OG image as a blob in the browser
  2. Uses client.assets.upload() to upload it to Sanity's CDN
  3. Attaches the resulting asset to your image field

Implementation Example

Here's how you could implement this:

import {useClient} from 'sanity'

function GenerateOGImageButton({documentId}) {
  const client = useClient({apiVersion: '2025-02-06'})
  
  const handleGenerateOGImage = async () => {
    // 1. Generate your OG image as a blob (using canvas, html2canvas, etc.)
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    // ... your image generation logic here
    
    // 2. Convert canvas to blob
    const blob = await new Promise(resolve => 
      canvas.toBlob(resolve, 'image/png')
    )
    
    // 3. Upload to Sanity
    const asset = await client.assets.upload('image', blob, {
      filename: `og-image-${documentId}.png`,
      contentType: 'image/png'
    })
    
    // 4. Update your document with the new image asset reference
    await client
      .patch(documentId)
      .set({
        ogImage: {
          _type: 'image',
          asset: {
            _type: 'reference',
            _ref: asset._id
          }
        }
      })
      .commit()
      
    console.log('OG image uploaded!', asset)
  }
  
  return (
    <button onClick={handleGenerateOGImage}>
      Generate og:image
    </button>
  )
}

Using as a Custom Asset Source

If you want to integrate this more deeply into the Studio's image field UI, you can create a custom asset source. Here's a simplified example:

// customOGImageSource.js
import React, {useCallback} from 'react'
import {Dialog, Card} from '@sanity/ui'

export default function OGImageGenerator({onSelect, onClose, document}) {
  const handleGenerate = useCallback(async () => {
    // Generate your blob
    const blob = await generateOGImageBlob(document)
    
    // Return it to Sanity's asset system
    onSelect([{
      kind: 'file',  // Using 'file' kind for blob/File objects
      value: blob,
      assetDocumentProps: {
        originalFilename: `og-image-${document._id}.png`,
        source: {
          name: 'og-generator',
          id: document._id
        }
      }
    }])
  }, [onSelect, document])

  return (
    <Dialog header="Generate OG Image" onClose={onClose} open>
      <Card padding={4}>
        <button onClick={handleGenerate}>Generate</button>
      </Card>
    </Dialog>
  )
}

// Asset source plugin definition
export const ogImageAssetSource = {
  name: 'og-generator',
  title: 'Generate OG Image',
  component: OGImageGenerator,
  icon: () => 'πŸ–ΌοΈ'
}

Then add it to your schema field:

{
  name: 'ogImage',
  type: 'image',
  options: {
    sources: [ogImageAssetSource]
  }
}

Key Points from the Documentation

Based on the custom asset sources documentation:

  • kind: 'file': When using onSelect in a custom asset source, use kind: 'file' for blob/File objects. The Studio will automatically handle uploading it to Sanity's CDN.
  • client.assets.upload(): This method (documented in the Sanity client GitHub repo) handles uploading blobs directly from the browser and returns an asset document
  • Asset reference structure: The uploaded asset needs to be referenced properly with {_type: 'image', asset: {_type: 'reference', _ref: assetId}}

CORS Consideration

If you're using kind: 'url' instead of kind: 'file', note that the resource must respond with an access-control-allow-origin header that allows the image to be read by the Studio host.

The blob will be automatically uploaded to Sanity's CDN, and you'll get back a proper asset document that you can reference in your image field! This is exactly what you're looking for in step (4) of your workflow.

Oh awesome. I'll watch it now. Thanks 😊
Exactly what I was looking for πŸ‘
user S
let me know if that helps. I need to create some offciial docmumentation around this
Hey it helped a lot! Inspired by you, I'm having a slightly different approach. I'm hosting sanity studio on vercel and created an api which generates image using puppeteer and set the image to the document using sanity client πŸ™‚
So the frontend of the studio just calls the api with
id, title, description
.

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?