Converting Sanity Block Content to HTML with Anchor Tags for JSON-LD
Based on the documentation, here's how to convert Sanity block content to HTML while preserving anchor tags:
Use @portabletext/to-html (Modern Approach)
The @sanity/block-content-to-html package you mentioned is deprecated. The modern replacement is @portabletext/to-html.
Here's how to use it and preserve links:
import {toHTML} from '@portabletext/to-html'
const portableText = [/* your block content from Sanity */]
const html = toHTML(portableText, {
components: {
marks: {
link: ({value, children}) => {
const href = value?.href || ''
const target = value?.blank ? ' target="_blank" rel="noopener"' : ''
return `<a href="${href}"${target}>${children}</a>`
}
}
}
})Handling Internal Links with Annotations
If you're using mark annotations for internal links, you'll need to join the reference data in your GROQ query first:
*[_type == "post"]{
...,
body[]{
...,
markDefs[]{
...,
_type == "internalLink" => {
"slug": @.reference->slug
}
}
}
}Then serialize with a custom component:
const html = toHTML(portableText, {
components: {
marks: {
internalLink: ({value, children}) => {
const slug = value?.slug?.current || ''
return `<a href="/${slug}">${children}</a>`
},
link: ({value, children}) => {
return `<a href="${value?.href || ''}">${children}</a>`
}
}
}
})Key Points
- Links are preserved automatically as long as you don't override the default serializers
- Use the
markscomponent to customize how link annotations are rendered - The library handles standard HTML output without classnames by default
- For JSON-LD FAQPage rich results, the plain HTML output (including anchor tags) works perfectly with Google's requirements
Check out the full documentation on presenting Portable Text for more examples and the @portabletext/to-html GitHub repo for detailed usage.
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.