Attaching images to Sanity editor using generated blobs
Yes, this is absolutely possible! You can generate an image in the browser (like an og:image), convert it to a blob, and upload it directly to Sanity's CDN using the client.assets.upload() method.
Here's how to accomplish what you're describing:
Uploading a browser-generated blob to Sanity
import {createClient} from '@sanity/client'
const client = createClient({
projectId: 'your-project-id',
dataset: 'your-dataset',
token: process.env.SANITY_WRITE_TOKEN, // You'll need a write token
apiVersion: '2025-02-06',
useCdn: false
})
// 1. Generate your og:image (example using canvas)
async function generateOgImage(title, description) {
const canvas = document.createElement('canvas')
canvas.width = 1200
canvas.height = 630
const ctx = canvas.getContext('2d')
// Draw your og:image content
ctx.fillStyle = '#000'
ctx.fillRect(0, 0, 1200, 630)
ctx.fillStyle = '#fff'
ctx.font = '48px sans-serif'
ctx.fillText(title, 50, 100)
// 3. Convert canvas to blob
return new Promise(resolve => {
canvas.toBlob(resolve, 'image/png')
})
}
// 4. Upload blob to Sanity
async function uploadOgImage(blob, documentId) {
const asset = await client.assets.upload('image', blob, {
filename: `og-image-${documentId}.png`,
contentType: 'image/png'
})
// 5. Attach to your document
await client
.patch(documentId)
.set({
ogImage: {
_type: 'image',
asset: {
_type: 'reference',
_ref: asset._id
}
}
})
.commit()
return asset
}
// Put it all together
async function handleGenerateOgImage(documentId, title, description) {
const blob = await generateOgImage(title, description)
const asset = await uploadOgImage(blob, documentId)
// 6. Use the URL in your og:image tag
const imageUrl = asset.url
console.log('og:image URL:', imageUrl)
return imageUrl
}Using with Custom Asset Sources
Since you mentioned looking at custom asset sources, you could also create a custom asset source plugin that integrates this generation directly into your Studio's image field. This would give your editors a "Generate og:image" button right in the image input.
Here's a simplified example of a custom asset source:
// customOgImageSource.js
export default {
name: 'og-image-generator',
title: 'Generate OG Image',
component: OgImageGenerator,
icon: () => 'π¨'
}
function OgImageGenerator({onSelect, document}) {
const handleGenerate = async () => {
const blob = await generateOgImage(document.title, document.description)
// Upload using the client
const asset = await client.assets.upload('image', blob, {
filename: `og-${document._id}.png`
})
// Return to the image field
onSelect([{
kind: 'assetDocumentId',
value: asset._id
}])
}
return <button onClick={handleGenerate}>Generate OG Image</button>
}Then configure it in your schema:
{
name: 'ogImage',
type: 'image',
options: {
sources: [
{name: 'og-image-generator', title: 'Generate', component: OgImageGenerator}
]
}
}Key Points
- The
client.assets.upload()method accepts blobs directly in the browser - You need a write token to upload assets
- The uploaded asset gets a permanent URL on Sanity's CDN that you can use in your
og:imagemeta tags - The asset is stored as a proper Sanity asset document and can be referenced from your content documents
This approach gives you a fully automated og:image generation workflow that stores the images properly in Sanity's asset system!
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.