Dynamic Blog Article using Next.JS

In this Forum post, I’ll explain how to create a dynamic blog post using Next.js.
This Paradigm can be applied to any framework.

1-Blog section template
Create a section template for the blog template.
Add the slug preview and give it a default value.
Add the Article preview and give it a default value referencing an Article.
Make the Preview URL dynamically generated .

return `http://localhost:3000/blog/${content.data.slugPreview}`

For more references on Dynamic Preview URLs, check out this document:

Create Your Blog Article Template UI using Builder.IO CMS

2- Article and Author model
→ Create Article and Author data model. Make sure to add ‘slug’ as a custom field in the
article model.

For a quick start, follow the blog article blueprint in The Builder website:

3- Create blog/[slug] for dynamic routing in Next.js
In Next.js app create your dynamic routing: blog/[slug]
Screenshot 2023-05-16 at 12.45.24 PM

3- Fetch blog template data and article data using [slug] as params at build time
Fetch the article data from the data model by querying the slug as the parameter.

export async function getStaticProps({ 
    params 
}: GetStaticPropsContext<{ slug: string[] }>) {
   const articleData =  
    (await builder
        .get('article',{
        query:{
            'data.slug': params?.slug
        }
     }).toPromise()) || null;

 const articleTemplate = await builder
    .get('blog-template', {
        options: {
            enrich: true,
        },
    }).toPromise();

  return {
    props: {
        articleData,
        articleTemplate   
    },
    revalidate: 5,
  };
}

5- Pre-render the Dynamic routes using getStaticPaths()

fetch all the articles using builder.getAll(model)

export async function getStaticPaths() {
  const articles = await builder.getAll('article', {
    options: {noTargeting: true},
    omit: 'data.blocks'
  })

  articles.map(article => console.log(`/blog/${article.data?.slug}`),)
  
  return {
    paths : articles.map(article => `/blog/${article.data?.slug}`),
    fallback: true,
  };
}

6- Render <BuilderComponent /> using blog template populated by the article data

On The client Side, get the blog template and populate it with article data queried using slug.

export default function Page({
     articleTemplate ,
     articleData
    }:InferGetStaticPropsType<typeof getStaticProps>) {
  const router = useRouter();
  if (router.isFallback) {
    return <h1>Loading...</h1>;
  }
  const isLive = !Builder.isEditing && !Builder.isPreviewing;

  if (!articleData && isLive) {
    return (
      <>
        <Head>
          <meta name="robots" content="noindex" />
          <meta name="title"></meta>
        </Head>
        <DefaultErrorPage statusCode={404} />
      </>
    );
  }

  return (
    <>
      <Head>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        {!articleData && <meta name='robots' content='noindex'/>}
      </Head>
       <BuilderComponent model="blog-template" 
                content={articleTemplate} 
                data={{article: articleData?.data}} 
        />
    </>
  );
}

The end result

Thanks for sharing your knowledge! As a beginner, I especially appreciate the screenshot and video.

Some feedback:

I personally tapped out here. I wouldn’t know what to do. What blog template? What section template? Are we starting from scratch? Where is my model? Where do I go? Give me a sign.

I would also love to understand the concept of a dynamic preview URL a little better (as opposed to a static one). I’ve posted a thread asking about it here but I still don’t really get it. If You could elaborate a bit and explain what the preview URL gives us over a static one in this use case I would be elated.