# Adding math support to a Gatsby MDX blog

I wanted to add support to display equations on my blog. A popular tool to achieve this is KaTeX.

The goal is being able to write a string in the TeX syntax inside a `.mdx`

file,
and a pretty math equation showing up on the rendered page.

My blog uses `gatsby-plugin-mdx`

to be able to use `.mdx`

files.

To achieve the goal of writing KaTeX blocks in MDX and getting pretty equations to show up, several things need to happen.

`gatsby-plugin-mdx`

allows you to pass plugins it will use internally.

We’ll use that to “make pretty math happen” 💅!

## Pinpoint the math sections in mdx

The first step is getting the MDX toolchain to recognize the math inside a `.mdx`

file.

I used the `remark-math`

plugin for this.
It takes your markdown, looks for the relevant math sections, and marks them as such.

An inline math section is opened with a single dollar sign, and ended by an other single dollar sign `$`

.

A math section that should be a block (so: it should start on a new line) is opened and closed by double dollar signs `$$`

.

1Some math on the same line: $T_n = a + (n-1)d$23Or, some math in a block45$$6T_n = a + (n-1)d7$$

The way markdown works has to do with Abstract syntax trees. They’re terribly complex at times, but they’re also very fascinating and extremely powerful tools.

`remark-math`

manipulates that tree in such a way that your inline math turns into an `inlineMath`

node,
and your block math turns into a `math`

node.

At the end of the MDX pipeline, HTML is rendered.

- The inline math blocks will turn into
`span`

s with a class of`math-inline`

. - A math block will turn into a
`div`

with a class of`math-display`

.

The content of those HTML-elements will be a string with the TeX you wrote in the `.mdx`

file.

So `$T_n = a + (n-1)d$`

turns into `<span class="math math-inline">T_n = a + (n-1)d</span>`

While the block

1$$2T_n = a + (n-1)d3$$

Turns into `<div class="math math-display">T_n = a + (n-1)d</div>`

### Wiring up remark-math

Install the `remark-math`

plugin, and add it to the configuration option of `gatsby-plugin-mdx`

in `gatsby-config.js`

.

1module.exports = {2 // --- snip ---3 plugins: [4 {5 resolve: "gatsby-plugin-mdx",6 options: {7 remarkPlugins: [require("remark-math")],8 },9 },10 // --- snip ---11 ],12};

## Doing something with that information

There are several ways to continue from here. Wichever way you choose, adding the required KaTeX CSS file whenever math is rendered is crucial.

### Option 1: a Rehype plugin

While a remark plugin like `remark-math`

does work on the AST of the mdx **before** it turned into HTML.

A rehype plugin does work **after** that HTML is generated and changes it.

You can use `rehype-katex`

for this.

It takes in those `<span class="math-inline">`

and `<div class="math-display">`

and turns the string of KaTeX you wrote
into something that’s ready to be rendered into a beautiful equation.
It just needs some of that CSS.

#### Wiring up rehype-katex

Install the `rehype-katex`

plugin,
and add it to the configuration option of `gatsby-plugin-mdx`

inside the `gatsby-config.js`

file.

npm i rehype-katex

1module.exports = {2 // --- snip ---3 plugins: [4 {5 resolve: "gatsby-plugin-mdx",6 options: {7 remarkPlugins: [require("remark-math")],8 rehypePlugins: [require("rehype-katex")],9 },10 },11 // --- snip ---12 ],13};

If you chose option 1, you’re done! Pretty math, yay!

### Option 2: a React component

I like the React workflow, so this is the option I chose.

It’s a bit more flexible, Should I ever want to use it outside of mdx, I can.

I take in those `<span class="math-inline">`

and `<div class="math-display">`

elements,
and give the string they contain to a React component to render correctly.

The React package I went with is @matejmazur/react-katex
.
It has a `<TeX />`

component that can turn the string of raw KaTeX into a form that’s ready to turn into a pretty equation on your screen.

#### Using `react-katex`

MDX allows you to intercept the HTML that gets rendered and add to, or replace it.

This is the mechanism I used to intercept those `<span class="math-inline">`

and `<div class="math-display">`

tags,
and give the contents to the `<TeX />`

component.

The `<MdxProvider />`

component from `@mdx-js/react`

allows this.
If you already have one of those in your app that wraps the `.mdx`

files you want to write math in, great!

If not, you can add one in Gatsby’s `wrapRootElement`

in both `gatsby-browser.js`

and `gatsby-ssr.js`

.
Or, in the layout component the `.mdx`

file will use.

*Yes, I know, there are a lot of moving parts here.*

1import React from "react";2import TeX from "@matejmazur/react-katex";3import { MDXProvider } from "@mdx-js/react";45const components = {6 div: (props) => {7 if (props.className.includes("math-display")) {8 import("katex/dist/katex.min.css");9 return <TeX block math={props.children} />;10 }11 return <div {...props} />;12 },13 span: (props) => {14 if (props.className.includes("math-inline")) {15 import("katex/dist/katex.min.css");16 return <TeX math={props.children} />;17 }18 return <span {...props} />;19 },20};2122export default function MdXLayout(props) {23 return <MDXProvider components={components}>{props.children}</MDXProvider>;24}

## Demo

For this blog, I chose the option that uses a React component.

I created a specialized `<MathBlock />`

component that handles math blocks,
and gives it some extra capabilities you can specify inside mdx, by adding options next to the opening `$$`

.

Inline math expressions are sent straight to the `<TeX />`

component.

= first item

= last item

= amount of items

= common difference

Input:

1Some inline math, coming right up. $T_n = a + (n-1)d$

Output:

Some inline math, coming right up.

### Using a `MathBlock`

explicitly

The MathBlock component can be used in two ways,
either by passing a KaTeX string to the `math`

prop,
or by including the KaTeX string in between the opening and closing tags.

#### Via the `math`

prop.

Input:

1import { MathBlock } from "./../src/components/MathBlock";2<MathBlock title="Arithmetic progression sum" math="S_n = \frac{n(a + l)}{2}" />

Output:

#### Via `children`

.

Input:

1import { MathBlock } from "./../src/components/MathBlock";2<MathBlock title="Arithmetic progression sum">34S_n = \frac{n(2a + (n-1)d)}{2}56</MathBlock>

Output:

### Using `$$`

signs in mdx

#### A vanilla block

Input:

1$$2S_n = \frac{n(2a + (n-1)d)}{2}3$$

Output:

#### With a meta string

Input:

1$$ title=Arithmetic-progression-sum2S_n = \frac{n(a + l)}{2}3\newline4S_n = \frac{n(2a + (n-1)d)}{2}5$$

Output: