Sanity Pioneers: Get early access to betas, extra AI credits, and a direct line to the engineering team. Apply now

How to query and render Sanity rich text/Portable Text as HTML?

5 repliesLast updated: Nov 29, 2025

Hi,
could you help me figure out how to use rich text from sanity?

Can I not query data from the field as HTML?

I can only see stuff like:

{
"content": [
    {
    "children": [
        {
        "text": Some bold text
        }
        {
        "text": some normal text.
        }
If I make some text bold, it becomes a child.

What am I missing?

Thanks!
AI Update

You're not missing anything! What you're seeing is exactly how Sanity's rich text works - it's called Portable Text, and it's a JSON-based format rather than HTML.

The structure you're seeing is intentional: bold text creates separate objects because marks (like bold, italic, etc.) are stored as metadata on text spans. This is why formatting changes create new "children" in the structure.

You cannot query Portable Text directly as HTML because it's stored as structured JSON data in Sanity's Content Lake. However, you have several options to convert it to HTML for display:

Rendering Options

1. Use @portabletext/react (React apps)

The modern, recommended approach:

import {PortableText} from '@portabletext/react'

<PortableText value={yourContent} />

2. Use @portabletext/to-html (Node.js/server-side)

For converting to HTML strings:

import {toHTML} from '@portabletext/to-html'
const html = toHTML(yourContent)

3. Use pt::text in GROQ (plain text only)

If you only need plain text without formatting, you can query:

*[_type == "post"] {
  "plainText": pt::text(content)
}

Note: This strips all formatting and just gives you the raw text.

Why Not HTML?

Portable Text's JSON structure actually gives you several advantages over storing HTML:

The serializers handle transforming that JSON structure into whatever format you need. You define how each block type, mark, and style should render in your specific application.

Note: The older block-content-to-html package is deprecated, so stick with the @portabletext/* packages for new projects.

Show original thread
5 replies

Was this answer helpful?

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.

Related contributions