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 model 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]
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