Skip to content




The only Sanity page-builder guide you'll ever need

The only Sanity page-builder guide you'll ever need

Wake up, it's 2025 and we need to build the best page builder we possibly can, where do we start, what is the code. Can I just copy your code?


Click me for the TL;DR (too long; didn't read)

Page builders suck, but Sanity's don't. Organize blocks, see previews, collaborate in real-time, and use flexible APIs. Use ?? for null checks. Try array groups and views. Seriously, read the docs next time. Or just let someone else handle it if you're too lazy.

I'm going to start this article by placing a bet that you've absolutely used a page-builder of some kind before. Let me fire off some quick opinions and tell me if they resonate.

  • They're hard to maintain
  • I can never find the block I want
  • Surely this can be more efficient

Yeah, I know, that's basically most of the experiences we've heard from clients. We want to change that by putting together this blog (opens in new tab) so I can scream at developers the next time I see a disorganised mess for a page builder.

Why Sanity page builders don't suck

The best opinion (my opinion)

I'm going to take a leaf out of Simeon's book (opens in new tab), and give you my opinions on page builders, and don't worry, they're unquestionably right and not to be disputed.

Here's how you should structure your previews in page builders

Setting up previews with Sanity Studio

How does this look in code?

Well, assuming you've called the title: title and your image field imageThis is the exact way I would set up a preview inside the code.

typescript
  preview: {
    select: {
      title: 'title',
      media: 'image',
    },
    prepare(selection) {
      const {title, media} = selection
      return {
        title: title ?? 'Currently no title, set one inside this block',
        subtitle: 'Split Image',
        media: media ?? ImageIcon,
      }
    },
  },

What are those ?? about?

If you haven't seen those before, or you have seen them and you don't know what the difference is between those and || I'll let you in on a little secret that's definitely not generated from ChatGPT...

  • || is the logical OR operator, returning the right operand if the left operand is falsy.
  • ?? is the nullish coalescing operator, returning the right operand only if the left operand is null or undefined.

Use ?? to specifically check for null or undefined values, ensuring that other falsy values like 0 or '' are not considered as missing values.

Or, in other words, because this asshole told me to use them.

Some developer we let live in our head rent free from LinkedIn called Joey Clover

Joey if you're reading this, I hope you're happy

Let's start with the new stuff

Before going further, let's talk about some of the new stuff that Sanity released that makes your page builder a bit better.

Array groups

Read the docs (opens in new tab)

This lets you split your page builder blocks (arrays of blocks) into groups. It means if you want to split out Forms and Heros. You can easily do it with some basic code.

Here's how it looks in the Sanity Studio:

Showing the array groupings on light mode. Honestly who even uses light mode in this day and age

And here's the code to do that:

typescript
{
  insertMenu: {
    groups: [
      {
        name: 'intro',
        title: 'Intro',
        // Here's where your blocks go to filter by intro
        of: ['hero'],
      },
      {
        name: 'storytelling',
        title: 'Storytelling',
        // Here's where your blocks go to filter by storytelling
        of: ['byTheNumbers']
      },
      {
        name: 'upsell',
        title: 'Upsell',
        // Here's where your blocks go to filter by upsell
        of: ['testimonials', 'hero'],
      },
    ],
  },
}

Fun fact: you can have a block in more than one grouping. It's pretty cool, for example, when you want a form block in both Forms and Engagement.

Array views

Read the docs (opens in new tab)

I know what you're thinking. Yeah, the above is pretty cool, but I still don't know what the hell my page builder block looks like, and it doesn't look like a 24px by 24px icon.

Well, first of all, you'd be right. Second of all, you now have something called array views. Yes, they're everything you're asking for.

They allow you to see a whole bunch of blocks at once with thumbnails. Here's the visuals that aren't ripped straight from the docs

Here's how it looks in the Sanity Studio

Array thumbnails looking pretty darn slick - you can see what you're going to drop into the page because of the chunky thumbnail

And here's the code to do that

typescript
{
  insertMenu: {
    // You don't have to use groups, just left them in
    groups: [
      {
        name: 'intro',
        title: 'Intro',
        of: ['hero'],
      },
      {
        name: 'storytelling',
        title: 'Storytelling',
      },
      {
        name: 'upsell',
        title: 'Upsell',
        of: ['testimonials', 'hero'],
      },
    ],
    views: [
      {name: 'list'},
      // This is the important bit
      {name: 'grid', previewImageUrl: (schemaTypeName) => `/static/preview-${schemaTypeName}.png`},
      // Remember you can create a folder called 'static'
      // In the root of your Sanity folder
    ],
  },
}

Sanity CMS development. Page builders, schema architecture, and editorial workflows your content team will actually enjoy.

Sanity Preferred agency partner

Pro tip: Use the same size canvas

Before you set this up, do everybody a favour and use the same size canvas for every screenshot, or else you're going to have a monstrosity of a visual representation of a block.

A nice, simple, and free way to handle this is to create a frame inside Figma and paste the screenshot into it, ensuring they are all the same height and width.

No spam, only good stuff

Subscribe, for more hot takes

Only god knows why anybody would purposefully subscribe themselves to a newsletter that moans about development. These poor souls did though
Profile 1
Profile 2
Profile 3
Profile 4
Profile 5

See it in action

It's not recycling content if nobody watched the video the first time round... So here it is again, packaged into a blog (opens in new tab). Please watch it.

Closing thoughts

I don't want to take you away from actually trying this yourself, so I implore you to stop reading this content and actually spin up Sanity and do this for your clients today. You will not believe the UX improvement from just integrating these changes above. If you want to go deeper on schema organization, check out our tips for building Sanity schema efficiently, and if your GROQ queries are getting out of hand, we have a guide on how to clean up your GROQ. If you are still deciding what to build this on, we also broke down which Sanity plan is right for you.

If, on the other hand, you can't be arsed and want somebody to "just sort it out for you," you can get in touch with the form below and we'll get you looking ship-shape in no time.

Frequently asked questions

What makes a Sanity page builder better than other page builders?
The usual complaints are that page builders are hard to maintain, you can never find the block you want, and they feel inefficient. Sanity addresses that with proper block previews, array groups to organise blocks, and array views that show a thumbnail of what each block looks like before you drop it in.
How should I set up block previews in Sanity Studio?
Select the block's title and image fields in the preview config, then use prepare to return a fallback title such as 'Currently no title, set one inside this block', a subtitle naming the block type (for example 'Split Image'), and a fallback icon when there is no image.
What is the difference between ?? and || in JavaScript?
|| returns the right operand whenever the left is falsy, which includes 0 and an empty string. ?? returns the right operand only when the left is null or undefined. Use ?? in preview fallbacks so legitimate values like 0 or '' are not treated as missing.
What are array groups in Sanity?
Array groups let you split your page builder blocks into named groups in the insert menu, such as Intro, Storytelling and Upsell, by listing which block types belong to each. A block can live in more than one group, so a form block can appear under both Forms and Engagement.
How do I show thumbnails of page builder blocks in Sanity?
Use array views. Add a views array to insertMenu with a list view and a grid view whose previewImageUrl returns a path such as /static/preview-{schemaTypeName}.png. Put the screenshots in a static folder at the root of your Sanity project and editors see a chunky thumbnail of each block.
What size should page builder preview images be?
Use the same canvas size for every screenshot, otherwise the grid looks like a mess. Our free method is to create a frame in Figma and paste each screenshot into it so they all share the same height and width.

About the author

Jono Alford

Founder of Roboto Studio, specializing in headless CMS implementations with Sanity and Next.js. A Sanity Pioneer and first-cohort Sanity Community Ambassador, focused on editorial experiences that help teams ship faster.



Related posts





Related videos





Get in touch

Tell us what you're building. We reply within one working day. Jono or someone on the team picks up every message personally.

By sending this you agree to our privacy policy. We only use your details to reply.