Sekrab Garage

Sanity.IO Tip

Querying GROQ for table of contents

Tip December 26, 22
Subscribe to Sekrab Parts newsletter.

A nice tip I came across when creating a Table of Contents based on H2 elements in an article on site using GROQ statements. Instead of serializing the content and then using DOM to find the H2 elements post-rendering, I adjusted the GROQ statement to get me the H2 elements in the body, in a separate array.

*[slug.current == "${slug}"&&_type=="post"] | order(publishedAt desc) 
  publishedAt, _id, 
  // ... other projections 
  // then this: get body's children where style of child is "h2", 
  // then project to text property only
  'toc': body[style == 'h2']{ 
    'text': children[0].text 

The body property is the field that holds the rich text (portable text in Sanity), and it is made up of arrays, each having a style property, which contains the HTML style used to generate the block. You can use any query depending on what you need to attain, here is a query cheat sheet.

The children is the sub-property of h2 and I know for a fact it has one element, you could have a different setup so take notice. That child has a property: text, and that is what I aim for.

Afterwards; I can set up the slug function locally, then post-process the H2 elements to have the id property set up as well. From that point forward it’s just vanilla.

Twenty-two is over.