How to add code blocks with syntax highlighting to a Next.js blog using MDX with Prism.js

Code blocks with syntax highlighting in Next.js

Table of contents

Prerequisites

I will be adding code blocks with syntax highlighting to the blog that I built in the tutorial video How to make a blog with Next.js, Strapi and GraphQL. You can also view the source code of the blog.

The blog uses the next-mdx-remote package which serializes the markdown from a Strapi CMS. You may also have your markdown files locally in your project e.g. my-first-blog-post.mdx. This tutorial will still work for you.

If you have not set up your project using next-mdx-remote, don't worry, step one will take you through it.

Step 1: Serialize your markdown with next-mdx-remote

If you have not got next-mdx-remote installed, run the following in your terminal

 npm install next-mdx-remote

OR if using yarn

yarn add next-mdx-remote

There are multiple ways to convert markdown from a CMS or file system to JSX. For this tutorial, we are using the serialize function from next-mdx-remote. Here is a snippet from the getStaticProps() function. This example is using GraphQL to pull down content from a CMS, but you might be pulling the markdown in from other sources.

[slug].js
export async function getStaticProps({ params }) {

    // Get data using GraphQL (This could also be REST API or local mdx files)
    const { data } = await client.query({
        query: GET_INDIVIDUAL_POST,
        variables: { slugUrl: params.slug }
    });

    const attrs = data.blogPosts.data[0].attributes;

    // Serialize the markdown
    const html = await serialize(attrs.content);

    return {
        props: {
            post: {
                title: attrs.title,
                content: html
            }
        }
    }
}

Then in the component we can put

[slug].js
export default function Post({ post }) {
    return (
        <div>
            <h1>{post.title}</h1>
            <MDXRemote {...post.content} />
        </div>
    )
}

The only code, other than CSS we need to change is the following from the snippet above.

[slug].js
    // Serialize the markdown
    const html = await serialize(attrs.content);

Step 2: Install rehype-prism-plus and rehype-code-titles packages

We are going to need to install two packages. You can do that by running the following

npm install rehype-prism-plus
npm install rehype-code-titles

OR if you're using yarn

yarn add rehype-prism-plus
yarn add rehype-code-titles

Step 3: Add mxdOptions to your serialize function

First import the packages into [slug].js, or wherever you serialize your markdown

[slug].js
import rehypePrism from 'rehype-prism-plus';
import rehypeCodeTitles from 'rehype-code-titles';

then add the following rehypePlugins to mdxOptions in the serialize function

[slug].js
    const html = await serialize(attrs.content, { mdxOptions: {
        rehypePlugins: [
            rehypeCodeTitles,
            rehypePrism
        ]
    } });

Step 4: Add a Prism.js theme

You need to add a Prism.js theme, which is just a single CSS file, to your project. Check out this long list of Prism.js themes. Choose one and add the CSS styles to your project so they are available globally.

Step 5: Add a code block to your markdown

Code blocks are added in markdown with three back ticks (`). Here is an example

## Lets code a for loop in C++

In this tutorial, we will loop through a for loop and print out the values of i

```cpp:main.cpp
for(int i = 0; i < 10; i++) {
     std::cout << i << std::endl;
}
```

Notice how we add the language we are using, separated by a colon, then the file name (optional). Prism.js supports a number of different programming languages.

The output from the code block in the above section is

main.cpp
for(int i = 0; i < 10; i++) {
     std::cout << i << std::endl;
}

That's it! You have now successfully added code blocks with syntax highlighting to your Next.js blog!


Image of the Author, Ryan Carmody

About the Author

Open for work

Hi, I'm Ryan from Adelaide, South Australia.

I'm a web developer and computer science tutor. I also rock climb, play wheelchair basketball and brew beer.

Check out some of the games I made

Retro Snake Game

Retro Snake

Eat the food but don’t hit the walls or your own body!

Retro Worldle

Worldle

Replica of the original but with extra features! Guess countries, flags and capitals.