MDX Markdown Components: How to Use and Reuse
Tags: react, javascript, gatsby
Published: 2020-06-26 12:58:09

> MDX syntax can be boiled down to being JSX in Markdown. It’s a superset of Markdown syntax that also supports importing, exporting, and JSX. - [mdxjs.com](https://mdxjs.com)

### Why do we need [MDX](https://mdxjs.com), what's wrong with our "traditional" markdown?

Well, if you don't already know: Modular = Good. Monolithic = Bad. 👌

That's true for our code and that's also true for our content. Building with [components](https://blog.bitsrc.io/independent-components-the-webs-new-building-blocks-59c893ef0f65), whether they are code or markdown, means easier maintainability and better reusability. All that translates to many other things like consistency in tech/ UIUX/ "voice & tone"/ everything).

MDX also makes it possible to incorporate JSX into our markdown and even build a design system to customize its styling(!)


### Demo: Using MDX with [Bit](https://bit.dev)

To fully enjoy the great merits of component-driven markdown, we'll publish all markdown components and all (styling) React components, to Bit.

> [Bit](https://bit.dev) is a tool and a component hub that makes publishing, documenting, and organizing components, quick and simple. 

>Bit doesn't require our project to be structured in any specific way. We simply publish independent components from... wherever.

Combining MDX with Bit means we don't have to work too hard to make our MDX/styling components available for reuse in other projects.

<a href="https://bit.dev"><img src="https://dev-to-uploads.s3.amazonaws.com/i/4qub6ab04n708i9snqsk.gif"></a>

### Our steps to composing a document and sharing its components:

1. Create a Gatsby blog site and set it up to use MDX

2. Write a few MDX markdown files (components)

3. Build a few React components for our markdown styling

4. Compose everything together into a single document

5. Publish both React and MDX components to Bit

***

### These should be our end results:

#### [The document](https://mdx-gatsby-demo.netlify.app/)

![](https://res.cloudinary.com/blog-assets/image/upload/v1593169242/MDX_Document_mffnes.jpg)
***

#### [Our published components on Bit.dev](https://bit.dev/eden/markdown-components)

![](https://res.cloudinary.com/blog-assets/image/upload/v1593169242/MDX_Collection_dpssx4.jpg)
***

### Let the coding begin!

#### 1. Create a Gatsby blog site and set it up to use MDX
We'll start with the 'gatsby-starter-blog' starter

```bash
$ gatsby new gatsby-starter-blog https://github.com/gatsbyjs/gatsby-starter-blog
```

Then, install all necessary MDX packages

```bash
$ npm install gatsby-plugin-mdx @mdx-js/mdx @mdx-js/react
```

Configure Gatsby's `gatsby-config.js` file to use the MDX plugin. Also, we'll set the `.md` \ `.mdx` as the extensions that should be handled.

```javascript
plugins: [
    {
      resolve: `gatsby-plugin-mdx`,
      options: {
        extensions: [`.mdx`, `.md`]
      },
    },
 // more plugins...
```

#### 2. Write a few MDX markdown components

We'll create a `src/components/content` directory for all our markdown components. [Check out the markdown files here](https://github.com/giteden/mdx-gatsby-demo/tree/master/src/components/content). 

For this demo, we'll make sure to use the `paragraph`, `header1 #`, `header3 ###`, `link []()`, and `code` markdown elements. We will customize their styling, later on.

#### 3. Build a few React components for our markdown styling

In this step, we'll create a few UI components using [styled-components](https://styled-components.com/). We'll place our components in a new `src/components/markdown-styles/` directory.

These components will make up what would essentially be our markdown design system.

For now, we'll simply build them - don't worry if it's not clear yet how they should actually be used for styling. It will all be cleared up, in our next step.

So, for example, our `CodeBlock` component that would later serve to style our markdown `code` element, will look like so:

```javascript
import styled from 'styled-components'


const CodeBlock = styled.pre`
    @import url(a-url-to-google-fonts);
    font-family: 'Source Code Pro', monospace;
    background-color: #000;
    color: #fafafa;
    padding: 20px;
    border-radius: 5px;
    display: block;
    overflow-x: auto;
    margin-right: 25px;
    margin-left: 25px;
`

export default CodeBlock;
```

#### 4. Compose everything together into a single document

As mentioned at the beginning of this tutorial - MDX files can be exported and imported. Notice how there's no `export x from 'path'` statement - you simply write the document and it's available for `import`.

To compose our two markdown components into a single document we'll import them to the `src/pages/index.js` file (this will be our one-and-only document)

```javascript
import React from 'react'

import ParagraphDefinition from '../components/content/ParagraphDefinition.md'

import ParagraphDefinitionHTML from '../components/content/ParagraphDefinitionHTML.md'


const Document = () => {
    return (
        <>
            <ParagraphDefinition />
            <ParagraphDefinitionHTML />
        </>
    )
}


export default Document;
```
We'll then wrap the MDX components with the `MDXProvider` context so that we could pass props for styling, down this markdown-component tree.

```javascript
// imports...
import {MDXProvider} from '@mdx-js/react'

const Document = () => {
    return (
        <MDXProvider>
            <ParagraphDefinition />
            <ParagraphDefinitionHTML />
        </MDXProvider>
    )
}


export default Document;
```

The `MDXProvider` is expecting a `components` prop. This will be an object that uses key-value pairs to map which markdown element should be styled by which UI component.

We'll import all UI components and set the `components` object, accordingly. 


```javascript 
// imports...
import Header1 from '../components/markdown-styles/Header1'
import Header3 from '../components/markdown-styles/Header3'
import Paragraph from '../components/markdown-styles/Paragraph'
import Link_ from '../components/markdown-styles/Link_'
import CodeBlock from '../components/markdown-styles/CodeBlock'

const components = {
    h1: Header1,
    h3: Header3,
    p:  Paragraph,
    a: Link_,
    pre: CodeBlock
}

const Document = () => {
    return (
        <MDXProvider components={components}>
            <ParagraphDefinition />
            <ParagraphDefinitionHTML />
        </MDXProvider>
    )
}


export default Document;
```
We now have a fully composed and styled markdown document! 🎉
![](https://res.cloudinary.com/blog-assets/image/upload/v1593169242/MDX_Document_mffnes.jpg)

***

#### 5. Publish both React and MDX components to Bit

We'll start by installing Bit's CLI tool

```bash
$ npm install bit-bin --global
```
We'll then go to our project's root directory and initialize a Bit workspace.

```bash
$ cd mdx-gatsby-demo
$ bit init
```
We'll then tell Bit which components it should track. Here, we'll mark all components under each directory with the `*` sign. We'll also add the `--namespace` flag to organize each group of components according to its function (styling or content). This will determine how our soon-to-be-published components are tagged in [Bit's component hub](https://bit.dev).

```bash
$ bit add src/components/content/* --namespace content

$ bit add src/components/markdown-styles/* --namespace markdown-styles
```

To compile our React components we’ll import and set a React compiler from [Bit’s ENVs collection](https://bit.dev/bit/envs). These compilers are pre-configured. No need to worry about setting bundling plugins, etc.

```bash
$ bit import bit.envs/compilers/react --compiler
```

We'll "tag" all tracked components with the `--all` flag. This will build, run tests (if there were any) and set a version to all components.

```bash
$ bit tag --all
```

To publish components, we'll first need to [signup](https://bit.dev) to a (free) Bit account and create a "component collection".

Once done, we can head back to our terminal, log in and publish.

```bash
$ bit login
$ bit export <username>.<collection-name>
```

We now have a [component collection](https://bit.dev/eden/markdown-components) for future markdown compositions and styling! 🎉

![](https://res.cloudinary.com/blog-assets/image/upload/v1593169242/MDX_Collection_dpssx4.jpg)

When exploring [The component collection on Bit](https://bit.dev/eden/markdown-components) you'll notice they can be filtered using the "namespace" filter. This is another way to make it easier to find what we need.