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} />;
}