Skip to main contentUpcoming webinar: Make Validation a Practice, Not a Phase. Save your seat.
CONTACT SALESSTART BUILDING
Landing pages
Blog Article
Hero Section
Navigation Links
Announcement Bar
Product Details
Product Editorial
Homepage
Request a blueprintGo to developer docs

Integrate Blog Article Building

enterprise plans

Builder's Visual Editor is especially powerful for creating rich blog article content. For an in-depth guide for how to make a blog in Builder, visit Create a drag-and-drop editable blog with Next.js.

Model definition

First, create a Section model in Builder named blog-article to store and create blog articles:

NameTypeNotes

Title

text

This is the article title when listing articles and for the page <title> tag for SEO; for example, "Announcing our new product line".

Handle

text

This is the URL handle; for example, new-product-line.

Image

file

This is the main image for the blog post — for example, when listing articles — as well as the og:image for previewing on social media sites like Facebook.

Date

timestamp

This is the date for displaying when this was posted and for filtering by date posted.

Blurb

text

Optional

This is the preview text when listing blog articles, and optionally can be the SEO meta description as well.

Author

reference

Optional

Use this to list info about authors. We recommend making a new data model—for example, with fields full name of type text and photo or type file—and using a reference type to reference the author for an article.

You can create as many additional fields as you like for additional product info.

Example code

Next, create a paginated blog article list that lists each article along with some info about each one. Example information can include an image, a title, and a link to view the blog article in detail.

Below is an example Blog article list in pages/blog/index.jsx:

import { builder } from "@builder.io/react";

builder.init(YOUR_KEY);

const ARTICLES_PER_PAGE = 30;

function Blog({ articles, pageNumber }) {
  return (
    <div>
      {articles.map((item) => (
        <Link href={`/blog/${item.data.handle}`}>
          <div css={{ overflow: "hidden", width: 300 }}>
            <div css={{ width: 300, height: 200, display: "block" }}>
              <img src={item.data.image} />
            </div>
            {item.data.title}
            {item.data.description}
          </div>
        </Link>
      ))}
      <div css={{ padding: 20, width: 300, margin: 'auto', display: 'flex' }}>
        {pageNumber > 1 && (
          <a href={`/blog/page/${pageNumber - 1}`}>
            ‹ Previous page
          </a>
        )}

        {articles.length > ARTICLES_PER_PAGE && (
          <a href={`/blog/page/${pageNumber + 1}`}>
            Next page ›
          </a>
        )}
      </div>
    </div>
  );
}

export async function getStaticProps({ query }) {
  // Get the page number from the path or query parameter
  // In this example we are hardcoding it as 1
  const pageNumber = 1;
  const articles = await builder.getAll("blog-article", {
    // Include references, like the `author` ref
    options: { includeRefs: true },
    // For performance, don't pull the `blocks` (the full blog entry content)
    // when listing
    omit: "data.blocks",
    limit: ARTICLES_PER_PAGE,
    offset: (pageNumber - 1) * ARTICLES_PER_PAGE,
  });

  return { props: { articles, pageNumber }};
}

export default Blog;

The next step is to create the Blog article detail page. This page will display the entire content of the blog. This will most likely be located in pages/blog/[article].jsx:

import {
  builder,
  BuilderComponent,
  BuilderContent,
  useIsPreviewing,
} from "@builder.io/react";
import Head from "next/head";
import DefaultErrorPage from "next/error";

builder.init(YOUR_KEY);

function BlogArticle({ article }) {
  const isPreviewing = useIsPreviewing();
  if (!article && !isPreviewing) {
    return (
      <>
        <Head>
          <meta name="robots" content="noindex" />
        </Head>
        <DefaultErrorPage statusCode={404} />
      </>
    );
  }

  return (
    // Wrapping the structured data in BuilderContent allows
    // it to update in real time as your custom fields are edited in the
    // Visual Editor
    <BuilderContent
      content={article}
      options={{ includeRefs: true }}
      model="blog-article"
    >
      {(content) => (
        <React.Fragment>
          <Head>
            {/* Render meta tags from custom field */}
            <title>{content?.data.title}</title>
            <meta name="description" content={content?.data.blurb} />
            <meta name="og:image" content={content?.data.image} />
          </Head>

          <div>
            <div>{content?.data.title}</div>
            {/* Render the Builder drag/drop'd content */}
            <BuilderComponent
              name="blog-article"
              content={content}
              options={{ includeRefs: true }}
            />
          </div>
        </React.Fragment>
      )}
    </BuilderContent>
  );
}

export async function getStaticProps({ params }) {
  const article = await builder
    .get("blog-article", {
      // Include references, like our `author` ref
      options: { includeRefs: true },
      query: {
        // Get the specific article by handle
        "data.handle": params.handle,
      },
    })
    .promise();

  return {
    props: {
      article,
    },
  };
}

export async function getStaticPaths() {
  return {
    // Optionally, use builder.getAll() to fetch all paths,
    // or just allow fallback: true to render any path
    paths: [],
    fallback: true,
  };
}

export default BlogArticle;

For an in-depth guide on how to make a blog in Builder, see Create a drag-and-drop editable blog with Next.js.