How to build a composable blog

su
sunilsandhu2 years ago

Introduction

Creating a blog from scratch requires quite a lot. There are a number of moving parts that come together to create a blog.

At Bit, we needed to build a blog that our team could use to create and post content. Staying true to our philosophy of creating components that are composable and reusable, we created The Bit Blog as a composition of the Blog component. Meanwhile, the Blog component is a composition of lots of other independent components.

In fact, this very blog post is a component, too!

Size doesn't matter

People tend to think of app components - or in this case, the Blog component - as "bigger" and components like a button as "smaller", but for us they are the same size. Both are simply components with different responsibilities.

All of the components used to compose the Blog, including the Blog component itself, are open sourced and available to install, import or fork here. You can choose to take any components from here to use however you see fit.

While the components you decide to use, and the compositions you choose to create, are purely up to you, here we will show you how to get started with creating your own composable Blog. For this, we will be using the Starter Blog composition to get you up and running.

Fun fact: The StarterBlog is just a composition of the Blog component!

Installation

To get started, you will need to have the Bit binary installed on your machine and configured to your PATH.

npx @teambit/bvm install
CopiedCopy

For a more advanced installation guide, head over to the installation section in our Docs.

Create a free bit.cloud account

bit.cloud is free for open source and personal use. It is a feature-rich platform for you to be able to upload and store all of your components. It is recommended to create your bit.cloud account prior to creating a workspace (more on this in the next section) to ensure the right owner name for your components.

Create your account

Create a workspace

The first step in the Bit journey is to initiate a new Bit Workspace. It is a development workspace for distributed, component-driven software.

Bit workspaces provide a structured environment for a variety of developer tasks. You can create new components, use existing components, modify existing components, and export changes. They allow for the development of all types of components.

Create a directory on your computer for your blog. Once you've created this, run the following command from inside the newly created directory: bit init. You're now ready to start creating components!

Want to know more about the files bit init creates?

Visit our page on starting new Bit workspaces in the Bit docs.

Now that we have the first time setup out of the way, let's start looking at components.

StarterBlog component

Post One

This is a post in a component-driven blog.

JD
Jane Doe2 years ago

Post Two

This is another post in a component-driven blog.

JD
Jane Doe2 years ago

You can either fork the component:

bit fork teambit.blog/starter
CopiedCopy

Or create a new component and use the code from the StarterBlog component as a reference:

bit create react my-blog
CopiedCopy

You can find more information about the Starter Blog component in the component's documentation. You can also do the exact same thing for any of the components we will be discussing, along with all of the components that belong to our Blog scope.

Wondering what a scope is?

You can find out more in the Scopes section of the Bit docs.

The Starter Blog is a composition of the Blog component. In other words, you pass whatever values, styles etc, you want to the Blog component's API (typically via props). That becomes your composition of the Blog.

As mentioned earlier, the Starter Blog component provides a starting point for you to get productive quickly with composing your own blog. So beyond that, you are not compelled to fork or create anything else. Any other times we mention forking or creating components is just so that you know how to do it, if you decide to.

Blog component

teambit.blog/blog
Preview Code

The Blog component forms the basis of all blog compositions. It's being used in The Bit Blog you are on right now, the Starter Blog we are discussing in this post, even this Demo Blog about cats and dogs. The key thing these three blogs have in common is that they are all compositions of the Blog component.

If you want to review the Blog component, you can either fork the component:

bit fork teambit.blog/blog
CopiedCopy

Or create a new component and use the code from the Blog component as a reference:

bit create react blog
CopiedCopy
Did you fork the StarterBlog?

If you did fork the StarterBlog, it will already include everything you need to create your own blog composition, so we only advise forking the other components if that's what you would prefer.

In the blog.tsx file, you will notice that this serves as a router for the following blog pages:

The Lobby page acts as the home page that a user would initially arrive on. The Label and Author pages serve as variations of the Lobby page, filtering content based on label or author URL params. The BlogPost page is the page that renders individual blog post content.

Each of these pages are components.

Just like all Bit components, they are versioned and released independently. While there are numerous benefits to this that apply to components in general, one particular benefit that stood out to us was that, because each page handles its own set of <meta> tags, our Marketing team is now able to go in and make tweaks to the meta tags for SEO purposes, independent from the rest of the Blog. Once they've made changes, they can tag and export a new version of the page they had been working on. This was just one of many game-changers we benefitted from with building a Blog out of Bit components.

You can learn more about the Blog's API in the component's docs.

Let's take a look at the Lobby and BlogPost components.

Lobby component

The Lobby page component is the home page of the blog. It will display all posts, ordered by recency by default.

You can either fork the component:

bit fork teambit.blog/pages/lobby
CopiedCopy

Or create a new component and use the code from the Lobby component as a reference:

bit create react pages/lobby
CopiedCopy

Note: The Blog component already ships with all of the above pages. If you wanted to add new pages, you would need to fork the Blog component and make the necessary adjustments. This is beyond the scope of this post, but we can look to cover this in the future.

Looking at the code for the Lobby component, you may notice that there is a prop called plugins. This gives you an interface to be able to 'extend' the blog, by adding additional features. More on this later.

You can learn more about the Lobby page's API in the component's docs.

Blog Post

The BlogPost component is responsible for rendering individual blog posts. It is a route/page in our Blog component.

You can either fork the component:

bit fork teambit.blog/pages/blog-post
CopiedCopy

Or create a new component and use the code from the BlogPost component as a reference:

bit create react pages/blog-post
CopiedCopy

The BlogPost component needs blog post content to render. People often think that components are reserved for UI elements. In reality, anything can and should be a component. With that in mind, blog post content is also a component, with each individual post being its own component.

Post Content

Individual blog post components are MDX files. MDX files are Markdown files that also allow for the rendering of React components.

You can either fork the component:

bit fork teambit.blog/starter/blog-posts/post-one
CopiedCopy

Or create a new component and use the code from the PostOne component as a reference:

bit create mdx blog-posts/post-one
CopiedCopy
Component environments

In the above snippet, we have written bit create mdx instead of bit create react. This is because we want to render an MDX component instead of a React component. Along with impacting on the structure of the component, picking mdx instead of react also changes the component's environment. Read more about environments (envs) here.

Once created, we can then look to pass that component to the Blog component. Currently, each blog post is passed to the Blog component via the contents prop which is an array, ready to receive each blog post as an object.

Contents array

An array of BlogPost content gets passed to the Blog component via the contents prop. The Starter Blog already has a contents.tsx file ready for use. contents.tsx is the file passed to Starter Blog component.

To get started quickly, you can simply edit the existing contents.tsx file, replacing the content with your own blog content.

But if you would prefer to create your own from scratch, you can copy the following structure:

const PostOne = loadable(() => import("@teambit/blog.starter.blog-posts.post-one"));

export const contents = BlogPostList.from();
CopiedCopy

You can then pass the following data structure as a parameter to BlogPostList.from():

[
  {
    title: "Hello World",
    description: "Lorem ipsum",
    createdAt: new Date(),
    author: {
      name: "Jane Doe",
      username: "jane",
      avatar: "https://placekitten.com/200/200",
    },
    component: <PostOne />,
    labels: [],
    metaData: {
      image: "",
      seoTitle: "",
      seoDescription: "",
      authorName: "",
      authorTwitter: "",
    },
  },
  {
    // ...another blog post
  },
];
CopiedCopy

In the code snippet above, you will notice that we create a PostOne variable which lazy loads our PostOne component - this component is simply the blog post content we created earlier. You will notice that PostOne, then, gets passed inside of an object (as component: <PostOne/>) to the contents array.

Pass multiple blog posts to the contents array

To pass more than one blog post, simply add multiple objects to BlogPostList.from([]).

Curious to know what BlogPostList is used for? In short, it is an entity that provides a data structure for listing blog posts. There's also a BlogPost entity that defines the structure of an individual blog post.

Extending the Blog component with plugins

The StarterBlog is rather modest. It has the prerequisite pages required for a fully functional blog, and works perfectly fine, but what if you want your composition to contain some extra features? Maybe you want your own composition to have a Hero at the top of the Lobby page, or maybe you want to have a Form component on certain pages for capturing newsletter signups.

Whatever additional functionality you wish to add, these can be added to your Blog composition with plugins. Plugins are also just components that get passed to your composition via the plugins prop on the Blog component.

In fact, the StarterBlog component actually ships with a UsefulLinks plugin to help demonstrate this feature.

You can either fork the component:

bit fork teambit/blog.starter.plugins.useful-links
CopiedCopy

Or create a new component and use the code from the UsefulLinks component as a reference:

bit create react plugins/useful-links
CopiedCopy

In our composition of the Blog component - aka The Bit Blog that you're currently reading this post on, we created a few plugins to serve our own needs. You can check any of them out at the links below:

Feel free to fork them and create your own variations to best suit your needs. Or go ahead and create your own, using these as inspiration.

Conclusion

While each page is composed of many other components, the contents of this post has hopefully provided a good foundation for you to get started with composing your own Blog out of existing Bit components. You can, of course, create your own components, fork existing components, and adjust as you see fit. Whatever you decide, be sure to tag us on Twitter with your compositions. We would love to see what you create!

To continue learning more, check out Bit docs.