The Sanity engineering blog is live. Deep dives from our engineers.

GraphQL not returning bullet and link types from Portable Text block

30 repliesLast updated: Nov 29, 2025

All portableText Elements come out in graphql as either on of the following types:
span
,
h2
,
h3
But not as
bullet
and
link
, although they are correctly formatted within Studio.
export default {
  name: 'pageTextSection',
  title: 'Page Text Section',
  type: 'document',
  fields: [
    {
      name: 'body',
      title: 'Body',
      type: 'array',
      of: [{type: 'block'}],
    },
  ],
}
Am I missing something here?
AI Update

You're not missing anything in your schema - this is expected behavior with how Portable Text structures data!

Bullets and links aren't separate block types - they're represented differently in the data structure:

Bullets (List Items)

Bullets are still blocks with _type: 'block', but they have additional properties:

In GraphQL, they come through as blocks, not as a separate "bullet" type. You need to check the listItem and level fields on the block to identify them.

Links are stored as annotations in the markDefs array, not as separate block types. The actual link text is still a span with a mark property that references the annotation. The structure looks like:

{
  "_type": "block",
  "children": [
    {
      "_type": "span",
      "text": "click here",
      "marks": ["abc123"]  // references the markDef
    }
  ],
  "markDefs": [
    {
      "_key": "abc123",
      "_type": "link",
      "href": "https://example.com"
    }
  ]
}

How to Handle This in GraphQL

When querying GraphQL, you'll need to:

This is all correctly formatted in Studio because the Portable Text editor understands this structure. Your GraphQL client needs to handle the same relationships when rendering.

I'd recommend using a Portable Text renderer library for your frontend framework to handle this complexity automatically - it will properly parse listItem, markDefs, and all the other Portable Text conventions for you. Check out the guide on presenting block text for more details on rendering Portable Text.

Show original thread
30 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