How to attach browser-generated blob as image in Sanity editor?
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
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:
- Generates your OG image as a blob in the browser
- Uses
client.assets.upload()to upload it to Sanity's CDN - 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 usingonSelectin a custom asset source, usekind: '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.
Show original thread5 replies
Was this answer helpful?
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.