Page Builder
Lesson 4

Creating a JavaScript switch for your page builder

You've created your perfect schema, you've improved your editorial experience by adding thumbnails and now it's time to get your page builder blocks wired up on the frontend.

Learning objectives

You are going to learn how to take the page builder components you've already created, and integrate them into the frontend of a Next.js project.

By the end of this chapter, you'll be able to:

  • Render the page builder in Next.js
  • Create a switch which shows the appropriate block dependent on your content in Sanity

Creating a query to fetch the page builder

You are going to create a query to fetch the page builder from Sanity. Let's break down what's happening in this query:

The -> operator in Sanity is used for dereferencing documents. When you have a reference to another document (like our FAQs), by default you only get the reference ID. Adding -> tells Sanity to "follow" that reference and include the full content of the referenced document in your query results. This is particularly useful when you need the actual content immediately and want to avoid making multiple separate queries.

queries/pageBuilder.ts
const pageBuilderQuery = groq`*[_type == "page" && slug.current == $slug][0]{
  ...,
  "pageBuilder": pageBuilder[]{
    ...,
    _type == "faqAccordion" => {
      ...,
      "faqs": faqs[]->
    }
  }
}`;

For example:

  • Without dereferencing (faqs[]): Returns array of reference IDs like ["ref1", "ref2"]
  • With dereferencing (faqs[]->) Returns array of full documents like [{title: "FAQ 1", body: "..."}, {title: "FAQ 2", body: "..."}]

Creating a switch to render the page builder

Now we have the blocks, we need to create a switch to render them. You can see there's the inclusion of a key, this is important for React to be able to render the blocks correctly. We have also passed the remaining props to the block component as a spread operator.

Not everybody has seen the spread operator syntax before, so here's a quick link to the docs (opens in a new tab).

page-builder.tsx
// References to our blocks
import { HeroBlock } from "./blocks/hero";
import { FeaturesBlock } from "./blocks/features";
import { TextAndImageBlock } from "./blocks/text-and-image";
import { FaqAccordion } from "./blocks/faq-accordion";
 
export function PageBuilderBlock({ pageBuilder }: PageBuilderProps) {
  // We need a null check here to avoid errors
  if (!Array.isArray(pageBuilder)) return null;
 
  return (
    <section>
      {pageBuilder.map((block) => {
        switch (block._type) {
          // We need to check for the block type here
          case "hero":
            return <HeroBlock key={block._key} {...block} />;
          case "features":
            return <FeaturesBlock key={block._key} {...block} />;
          case "textAndImage":
            return <TextAndImageBlock key={block._key} {...block} />;
          case "faqAccordion":
            return <FaqAccordion key={block._key} {...block} />;
          default:
            // This is a fallback for when we don't have a block type
            return <div key={block._key}>Block not found: {block._type}</div>;
        }
      })}
    </section>
  );
}

Now you've created a switch to render the page builder. In the next lesson, you'll learn how to get the most out of the visual editor with drag and drop functionality.