How to Replace Types on Images without Re-adding Each Image for Every Object/Document
Good news! You don't have to re-add all your images. You can migrate your existing image data to use the new custom image type through a migration script.
Since Sanity's backend is schemaless, your existing image data is still there even after you change the schema. The key is to write a migration script that transforms your existing documents to add the new fields (like alt text) while preserving the existing image references.
Here's the general approach:
Update your schema to use your new
customImagetype where you previously hadtype: 'image'Write a migration script that:
- Queries all documents with the old image structure
- Transforms them to match your new custom image structure
- Preserves the existing
_refto the image asset
Here's an example migration script:
import {getCliClient} from 'sanity/cli'
const client = getCliClient()
const fetchDocuments = () =>
client.fetch(`*[_type == "yourDocType" && defined(yourImageField._ref)]`)
const buildPatches = (docs) =>
docs.map((doc) => ({
id: doc._id,
patch: {
set: {
yourImageField: {
_type: 'customImage',
asset: {
_type: 'reference',
_ref: doc.yourImageField._ref // Preserve existing image reference
},
alt: '' // Add default alt text, or derive from existing data
}
}
}
}))
const createTransaction = (patches) =>
patches.reduce(
(tx, patch) => tx.patch(patch.id, patch.patch),
client.transaction()
)
const migrateNextBatch = async () => {
const documents = await fetchDocuments()
const patches = buildPatches(documents)
if (patches.length === 0) {
console.log('No more documents to migrate!')
return null
}
console.log(`Migrating batch:\n %s`, patches.map((patch) => patch.id).join('\n'))
const transaction = createTransaction(patches)
await transaction.commit()
return migrateNextBatch()
}
migrateNextBatch().catch((err) => {
console.error(err)
process.exit(1)
})Key principles from Sanity's migration best practices:
- Idempotent scripts: Make sure you can run the script multiple times safely
- Incremental approach: Test on a few documents first, then scale up
- Preserve asset references: The
_refto your image asset stays the same, so you're not re-uploading images
You can also use the deprecated field feature to mark old fields during the transition period, so they're visible on documents that still have them but hidden on new documents.
For more complex migrations, check out the schema and content migrations documentation and the handling schema changes course.
Show original thread1 reply
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.