How to Add Syntax Highlighting to Next.js Project with Remark and Prism.js

If you are like me, chances are you are new to blogging with Next.js or manipulating markdown.

Especially, syntax highlighting was a whole new thing to me (and still is).

When I started creating this blog, I followed the official tutorial of Next.js about creating a blog using the framework. The document encourages to use remark to convert markdown string into HTML string, and I'm still using the library. However, it didn't tell me how to make codes in markdown-based HTML look good, so I had to research.

Although there were many articles about adding syntax-highlighter to a Next.js-based static page application, they tend to show how to do it with React Markdown library instead of remark.

So I thought it would be great to share how to add syntax-highlighter to markdown-based HTML using remark specifically.

What is remark, by the way?

According to the official website, remark is a Markdown processor powered by plugins part of the unified collective. In plain English, you can accomplish a specific task regarding Markdown with the library and a plugin tailored for the job. Say, you can convert Markdown files or strings into HTML strings with the plugin called remark-html. Like so, if you want to add syntax-highlighting, you might want to use a specific plugin. In this article, I will use remark-prism.

Enough talking; let's get down to business.

Prerequisites

  1. you use TypeScript
  2. you've already downloaded the remark and remark-html library
  3. the function that converts Markdown into HTML looks like this;
import remark from "remark";
import html from "remark-html";

export const processMarkDown = async (markdown: string) => {
  const processedContent = await remark()
    .use(html)
    .process(markdown)
    .catch(() => "there was an error, please try again");
  return processedContent.toString();
};

First thing first

Let's download remark-prism by this command ;

yarn add remark-prism

Secondly

Edit the file that processMarkDown function is defined like below;

import remark from "remark";
import html from "remark-html";
import prism from "remark-prism"; // <-import prism here

export const processMarkDown = async (markdown: string) => {
  const processedContent = await remark()
    .use(html)
    .use(prism) // <-use prism here
    .process(markdown)
    .catch(() => "there was an error, please try again");
  return processedContent.toString();
};

The first important line of code is this;

import prism from "remark-prism";

The second thing to note here is that I added use(prism) in the method chain. This is where you add class names to HTML tags where necessary for syntax highlighting. But without the next procedure, you can't ornament codes.

Last but not least

In the _app.tsx, add one particular line to apply syntax-highlighting to the entire project.

import type { AppProps } from "next/app";
// add this line
import "prismjs/themes/prism-tomorrow.css";

function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />;
}

export default MyApp;

By adding import "prismjs/themes/prism-tomorrow.css", you can finally apply syntax-highlighting to codes. But many tutorials and blog articles somehow miss this step, which kept me confused for a while.

Anyway, this should make your codes look pretty!

You can also tinker with the taste of styling by importing different CSS files made for prism. You can see the list from this GitHub link.

Conclusion

Since I've seen Markdown-based blog articles using syntax-highlighting a lot, I didn't expect actually finding a way to do it to be this confusing. It turns out each step is easy and simple, but I don't know why I couldn't find the solution easily. So I hope this article helps other newbies who started out writing their blogs.

Thanks for reading.