Question about handling a rich text field in the createOrReplace function with the Sanity JavaScript client.
When working with Portable Text (rich text) fields in Sanity using the JavaScript client's createOrReplace method, you need to provide data in the proper Portable Text format - an array of block objects, not just a plain string.
Here's the structure you need for a basic Portable Text field:
await client.createOrReplace({
_id: 'your-document-id',
_type: 'yourDocumentType',
description: [
{
_type: 'block',
_key: 'uniqueKey1', // Generate a unique key
style: 'normal',
children: [
{
_type: 'span',
_key: 'uniqueKey2',
text: 'Your text content goes here',
marks: []
}
],
markDefs: []
}
]
})The key components of a Portable Text block are:
_type: 'block'- Identifies this as a text block_key- A unique identifier for the block (you can generate these with a library likenanoidor just use timestamps)style- The block style (e.g., 'normal', 'h1', 'h2', 'blockquote')children- An array of text spansmarkDefs- Definitions for annotations (like links)
For a helper function to convert plain text to Portable Text format:
function textToPortableText(text) {
return [
{
_type: 'block',
_key: Date.now().toString(),
style: 'normal',
children: [
{
_type: 'span',
_key: (Date.now() + 1).toString(),
text: text,
marks: []
}
],
markDefs: []
}
]
}
// Usage
await client.createOrReplace({
_id: 'doc-id',
_type: 'yourType',
description: textToPortableText('Your content here')
})For more complex scenarios with multiple paragraphs or formatting, check out the @sanity/block-tools package which can help convert HTML or other formats to Portable Text.
You can read more about Portable Text structure in the Portable Text specification and the Block Content guide.
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.