Converting portable text to markdown or HTML in Sanity page builder
Good news and some workarounds for you! You're right that Sanity has a limitation: arrays cannot contain other arrays due to a data store constraint. This means you can't directly nest a portable text field (which is an array of blocks) inside an array-based page builder.
However, there are a couple of solutions:
Solution 1: Use an Object Type (Recommended)
Instead of putting portable text directly in your page builder array, wrap it in an object type. Objects can contain arrays, so this works perfectly:
{
name: 'pageBuilder',
type: 'array',
of: [
{
name: 'mediaWithContent',
type: 'object',
fields: [
{
name: 'image',
type: 'image'
},
{
name: 'content',
type: 'array', // This is your portable text
of: [{type: 'block'}]
}
]
}
]
}This is the standard pattern and what most developers do. The page builder array contains objects, and those objects contain your portable text array. The limitation exists in the data store, but wrapping nested arrays in objects is the recommended workaround.
Solution 2: Reference a Separate Document
Create a separate document type that contains your image + portable text, then reference it from your page builder. This is useful if you want to reuse these content blocks across multiple pages.
Converting Portable Text to Markdown
For converting portable text to markdown in your 11ty setup, you'll want to use the official @sanity/block-content-to-markdown package:
npm install --save @sanity/block-content-to-markdownThen in your 11ty templates or data files:
const toMarkdown = require('@sanity/block-content-to-markdown')
const markdown = toMarkdown(portableTextArray)If you have custom blocks or marks in your portable text, you'll need to provide custom serializers to handle those:
const serializers = {
types: {
code: props => '```' + props.node.language + '\n' + props.node.code + '\n```'
}
}
const markdown = toMarkdown(portableTextArray, {serializers})The package documentation has good examples of handling custom serializers for different block types and marks.
The object-wrapping approach is definitely the way to go here - it's a well-established pattern in the Sanity community and works seamlessly with all the tooling. Welcome to Sanity, and hope this helps! 🎉
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.