
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeYes, 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:
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
}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}
]
}
}client.assets.upload() method accepts blobs directly in the browserog:image meta tagsThis approach gives you a fully automated og:image generation workflow that stores the images properly in Sanity's asset system!
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.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store