Building React Components from headless CMS markdown

Stefan Kudla
|React|Originally published at
Cover image for Building React Components from headless CMS markdown

Markdown has become a staple in my workflow as a developer and content creator. It’s quick to write, flexible with its features, and has easy-to-remember syntax.

Using React Markdown, we’re going to create Custom React Components (in a Next.js application) using parsed markdown retrieved from a headless CMS. By doing so, we will be able to quite easily utilize cutting-edge features like Next Image in the body of our Markdown. This way, we can take dynamic content and shape it the way we want, improving performance, accessibility, and overall user experience.

mdn to html

This article features the Next.js Developer Portfolio Template I built with Cosmic. You can follow along by visiting the App Template Page and importing the template into your own Cosmic Bucket (create an account if you’d like to follow along this way and haven’t already made one). Or, view the source code if you’d rather follow along with your own application.

A brief overview of React Markdown

React Markdown is a React Component to render markdown which lets you create and render custom components instead of standard HTML components. It is safe by default (no ) and allows you to use a wide array of plugins from remarkjs to enhance your markdown.

Diagram of the react markdown architecture flow

To further understand this component, let’s reference the diagram above step-by-step.

  1. The markdown content is parsed and turned into a markdown syntax tree
  2. The markdown syntax tree is transformed to an HTML syntax tree through remark
  3. The HTML syntax tree is transformed through rehype, and rendered to React components.

Installing the packages

To use react-markdown, we only need the package itself.

To retrieve our data from Cosmic, we can install the Cosmic NPM module.

Getting our Markdown content from a headless CMS

In this example, we’re retrieving markdown content from a Cosmic Object that is going to be the body of text for an article. Within the pages directory of our Next.js application, make sure you have a file created within a folder called , , or whatever you please.

We can import the package, set the environment variables, then write two functions that will get data from our Cosmic dashboard.

Within our file, we can call and , pull in data, then pass it through to our component.

Now that we’ve got the page itself set up, let’s dive into our component, where we will be using react-markdown to render our content.

Implementing React Markdown

Within our we can import and use the Component. We simply import the package and wrap our content in the component.

Creating custom components

Furthermore, we can create custom components. To do this, we will create a object above our component and pass it through to the component.

When creating the custom components, the key will be the HTML equivalent for the content we write in markdown. The parameter will be what you want to render as an HTML element, and will have access to the props of that element. For example, the element will give us access to and and the tag and .

The JSX you write within these functions will return the provided element. You could write something like and you will render elements for every written in markdown.

My favorite use case so far has been implementing Next Image for optimized image sizes and better page load times.

Without using Next Image, having lots of images in our markdown will require all of the images to be loading when the page is requested. This is slow and negatively impacts user experience and lighthouse scores.

When I refresh the page, all of the images will be loaded at once. Yikes!

Loading all images on a web page without lazy loading

Let’s improve this! Import from , then create a custom component inside of the object. Remember, we have access to some standard props with these components, so we can simply grab the and from the . We pass them into our component written in our JSX, defining a set and , a lower to the file size, and a of to serve scaled images according to screen size, ensuring that small devices don’t receive any unnecessarily large file sizes.

Now that we’ve added the custom component, let’s reload the page and see the magic.

Loading images on a web page with Next Image and lazy loading

We are no longer requesting all of those images at once, and as we scroll down the page, the lazy loaded images start to appear in the network tab.

Having the flexibility to create custom React Components for markdown is essential and with react-markdown, we can achieve this in just a few lines of code. Boosting performance, increasing link security, and having overall increased capabilities for our markdown data are what we achieve here. Aside from the improvements within our application, this component is super easy to use and taps us into the unifiedjs (giving us superpowers!).

Come build some cool sh!t with us! You can tune into our new show Build Time, where we cover topics like headless CMS, Next.js, React, and many many more.