Editing of section model fields not visible in live editor - NextJS 14 app router

Builder content link

Builder public api key
87f7e6ddda884039ad862d083035a471

What are you trying to accomplish
I want to create a blog post template, so I created a blog post model. I want the title, main image and date to always be on the page in a certain format, so I coded those in my /blog/[…postUrl]/page.tsx. I also want my clients to be able to write the blog post however they want, so below the title, image, etc. I added the RenderBuilderContent component so that they can do that.

The content is rendered correctly and I can add content to the blog, but when I change the fields of the blogpost model (e.g. the title), I don’t see the changes live in the editor or in the draft. I have to publish the content, wait a few seconds, then refresh the page. Also, when I change the Url field, I instantly get a 404 page. Then again, I have to publish the changes and wait some time before I can see the content on the new Url.

I tried converting my page.tsx to a client component and using UseEffect to fetch te content on the page, but then I still had to refresh te page to see the changes. That is a bit better because I didn’t have to publish te content to see the changes, but it’s still not live editing and I want my pages to be rendered on the server for SEO.

Screenshots or video link
This is what my editor looks like. This is how it should be, but I want to see the changes that I make in the input fields on the right side (title, date, shortText) live in the editor.

Code stack you are integrating Builder with
@builder.io/react 3.2.6
@builder.io/sdk 2.2.2
next 14.2.1
react 18.2.0

Code

import { Builder, builder } from "@builder.io/sdk";
import { RenderBuilderContent } from "@/components/builder";
import MainWrapper from "@/components/layouts/MainWrapper";
import { BlogPost } from "../page";
import Image from "next/image";
import { BuilderContent } from "@builder.io/react";
import Title from "@/components/Standard/Title";
import Text from "@/components/Standard/Text";
import NotFound from "@/app/[...page]/not-found";

builder.init(process.env.NEXT_PUBLIC_BUILDER_API_KEY!);

interface PageProps {
  params: {
    postUrl: string;
  };
}

export async function generateStaticParams() {
  const articles = await builder.getAll("blogpost", {});

  return articles.map((article) => ({
    params: {
      postUrl: article?.data?.url,
    },
  }));
}

type BlogPostFull = BlogPost & {
  data: {
    date: string;
    content: BuilderContent;
    tags: string[];
  };
};

export default async function BlogArticle(props: PageProps) {
  const content: BlogPostFull = await builder
    .get("blogpost", {
      prerender: false,
      // Include references, like the `author` ref
      options: { includeRefs: true },
      query: {
        // Get the specific article by handle
        "data.url": props?.params?.postUrl?.toString(),
      },
    })
    .toPromise();

  if (!content) {
    return NotFound();
  }

  const formattedDate = new Date(content.data.date).toLocaleDateString(
    "Nl-nl",
    {
      year: "numeric",
      month: "long",
      day: "numeric",
    }
  );
  return (
    <>
      <div className=" prose-headings:font-rodetta prose-headings:font-bold text-neutral-content">
        <MainWrapper className="max-w-[850px] gap-5">
          <div className="w-full relative h-96">
            <Image
              src={content.data.mainImage}
              alt="alt"
              layout="fill"
              objectFit="cover"
              priority={true}
            />
          </div>
          <div className="">
            <Title order={1} text={content.data.title} />
            <Text text={formattedDate} className="italic" />
          </div>
          <Text
            text={content.data.shortText}
            className="font-semibold text-lg"
          />

          <RenderBuilderContent content={content} model="blogpost" />
        </MainWrapper>
      </div>
    </>
  );
}

"use client";
import { ComponentProps } from "react";
import { BuilderComponent, useIsPreviewing } from "@builder.io/react";
import { BuilderContent, builder } from "@builder.io/sdk";
import DefaultErrorPage from "next/error";
import "../builder-registry";

type BuilderPageProps = ComponentProps<typeof BuilderComponent>;

// Builder Public API Key set in .env file
builder.init("87f7e6ddda884039ad862d083035a471"!);

export function RenderBuilderContent({ content, model }: BuilderPageProps) {
  // Call the useIsPreviewing hook to determine if
  // the page is being previewed in Builder
  const isPreviewing = useIsPreviewing();
  // If "content" has a value or the page is being previewed in Builder,
  // render the BuilderComponent with the specified content and model props.
  if (content || isPreviewing) {
    return <BuilderComponent content={content} model={model} />;
  }
  // If the "content" is falsy and the page is
  // not being previewed in Builder, render the
  // DefaultErrorPage with a 404.
  return <DefaultErrorPage statusCode={404} />;
}

Hello @tobias,

You may need to use BuilderContent for live editing to work,

Example:

          <BuilderContent
            content={article}
            options={{ includeRefs: true }}
            model="blogpost"
          >
            {(data, loading, fullContent) => (
              <>
                <Head>
                  <title>{data?.title}</title>
                  <meta name="description" content={data?.blurb} />
                  <meta name="og:image" content={data?.image} />
                </Head>
                <div>
                  <BuilderComponent
                    model="blogpost"
                    content={fullContent}
                    options={{ includeRefs: true }}
                    data={{ article }}
                  />
                </div>
              </>
            )}
          </BuilderContent>

Additionally, you can refer to the below blog post for reference

Hope this helps!

Thanks,

Hello @manish-sharma, thank you for your reply.

When I try the method you suggested, I get this error:
“TypeError: (0 , react__WEBPACK_IMPORTED_MODULE_1__.createContext) is not a function”.

How can I resolve this? I saw something about using another experimental sdk, is that the only way to make it work? Does this method even make it work?

Hello @tobias,

If you’re utilizing the Next.js 14 app router with server-side components, we recommend using our Next.js experimental SDK. However, if you’re not utilizing any server-side components, you can opt for our SDK v1 or SDK v2.

You can find the Next.js experimental SDK example at the following link:

For further comparison between our SDK versions, you can refer to our documentation here:

Thanks,

Hello @manish-sharma. I configured the gen 2 SDK and it works, but I cannot find in your documentation how I can make a component accept children. Can you explain that to me or provide a link to where that is explained in your documentation? Thank you :smiley: