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