Main hero image

How to Add Syntax Highlighting to <pre> and <code> Tags in a Remix App

As a full-stack developer, adding syntax highlighting to your website can make a world of difference, especially when presenting code snippets. If you’re building a blog or documentation site with Remix and Markdown, you’ll likely want to showcase code blocks in a clean, readable way. In this post, I’ll walk you through how to install and configure syntax highlighting in your Remix project using a popular package: rehype-prism-plus.

We’ll cover the following:

  1. Why syntax highlighting matters
  2. What packages to use in Remix for syntax highlighting
  3. Step-by-step installation and configuration of rehype-prism-plus
  4. How to render Markdown with highlighted code snippets in Remix

By the end, you’ll have a Remix app that renders your <pre> and <code> blocks with beautiful syntax highlighting!


Why Syntax Highlighting Matters

If you’re building a website that displays code, syntax highlighting greatly improves the user experience. Highlighting different parts of the code (keywords, comments, variables, etc.) makes it easier to read and comprehend. Whether you’re writing tutorials, showcasing examples, or building developer-focused content, syntax highlighting adds both clarity and visual appeal.

Without syntax highlighting, code blocks can appear flat and are more difficult to scan. With the help of tools like Prism.js, you can make your code stand out and become more accessible.

Using rehype-prism-plus for Syntax Highlighting

There are several ways to add syntax highlighting to a Remix app, but a great option is to use rehype-prism-plus with a Markdown processor like remark and rehype. This setup is ideal if you want to:

  • Write your articles or posts in Markdown
  • Automatically highlight code blocks as they are rendered

Here’s a quick breakdown of the key tools we’ll use:

  • remark: A Markdown processor that helps transform Markdown into HTML.
  • rehype: A tool that takes HTML output and enhances it (in this case, by adding syntax highlighting).
  • rehype-prism-plus: A plugin that integrates with rehype to add syntax highlighting using Prism.js.

Step-by-Step Guide to Adding Syntax Highlighting in Remix

1. Set up your Remix project

If you haven’t already set up a Remix project, you can create one using the following command:

npx create-remix@latest

Follow the prompts to create a new project. Once the setup is complete, you can navigate into your project directory.

2. Install the necessary packages

We need to install several packages to enable Markdown processing and syntax highlighting:

  • remark: The core Markdown processor
  • remark-html: To convert Markdown into HTML
  • rehype-prism-plus: For syntax highlighting using Prism.js
  • rehype-raw: To handle raw HTML output from Markdown
  • gray-matter: To parse front-matter in Markdown files

Run the following command to install all the required packages:

npm install remark remark-html rehype rehype-raw rehype-prism-plus gray-matter

3. Set up the Markdown processing utilities

Create a utility function to handle Markdown processing. This function will:

  1. Parse the Markdown content using remark
  2. Convert it to HTML
  3. Add syntax highlighting to code blocks using rehype-prism-plus

Create a file app/utils/markdown.server.js with the following content:

import { remark } from 'remark';
import html from 'remark-html';
import rehypeRaw from 'rehype-raw';
import rehypePrism from 'rehype-prism-plus';
import rehype from 'rehype';
import grayMatter from 'gray-matter';

export async function parseMarkdown(markdown) {
  const { content } = grayMatter(markdown);

  // Process the markdown with syntax highlighting
  const result = await remark()
    .use(html)
    .process(content);

  const htmlContent = result.toString();

  // Rehype for adding syntax highlighting
  const highlightedHtml = await rehype()
    .data('settings', { fragment: true })
    .use(rehypeRaw)
    .use(rehypePrism)
    .process(htmlContent);

  return highlightedHtml.toString();
}

4. Create a route to display posts with syntax highlighting

Next, you’ll need to create a route in Remix that loads and renders a Markdown post with syntax highlighting. Let’s create a dynamic route for blog posts.

Create a new file: app/routes/posts/$slug.jsx

import { useLoaderData } from "@remix-run/react";
import { json } from "@remix-run/node";
import fs from "fs";
import path from "path";
import { parseMarkdown } from "~/utils/markdown.server";

export async function loader({ params }) {
  const postPath = path.join(__dirname, "..", "posts", `${params.slug}.md`);
  const postMarkdown = fs.readFileSync(postPath, "utf-8");
  const postHtml = await parseMarkdown(postMarkdown);

  return json({ postHtml });
}

export default function Post() {
  const { postHtml } = useLoaderData();

  return (
    <article>
      <div dangerouslySetInnerHTML={{ __html: postHtml }} />
    </article>
  );
}

This route:

  • Reads a Markdown file from the posts folder.
  • Passes the content through the parseMarkdown function we set up earlier, which converts the Markdown to HTML and adds syntax highlighting to the code blocks.
  • Uses dangerouslySetInnerHTML to safely render the processed HTML in the browser.

5. Create a Markdown post with code snippets

Let’s create a sample Markdown file in the posts directory with some code blocks. The directory structure should look something like this:

/app
  /posts
    my-first-post.md

In my-first-post.md, you could have something like this:

---
title: "My First Post with Syntax Highlighting"
slug: "my-first-post"
date: "2024-10-05"
---

# Hello World!

This is a simple blog post to demonstrate syntax highlighting.

Here's some JavaScript:

```js
function sayHello(name) {
  return `Hello, ${name}!`;
}

And here’s some CSS:

body {
  background-color: #f0f0f0;
  color: #333;
}

6. Add Prism.js CSS for syntax highlighting styles

The syntax highlighting won’t look styled yet because we haven’t added the Prism.js CSS. You’ll need to include Prism’s CSS styles in your project. You can add them via a CDN or install them locally.

For now, let’s include the CSS file by adding a <link> to your root HTML file.

In app/root.jsx, add the following inside the <head> tag:

<link
  href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/themes/prism-tomorrow.min.css"
  rel="stylesheet"
/>

This will pull in the Prism Tomorrow theme, which is a dark theme for code highlighting. You can replace it with other themes if you prefer something different.

7. Testing Your Code

With everything set up, you can now test your site. Start your Remix development server:

npm run dev

Visit the URL corresponding to one of your posts (e.g., http://localhost:3000/posts/my-first-post). You should now see your blog post rendered with proper syntax highlighting for the JavaScript and CSS code blocks.

Conclusion

By following these steps, you’ve added beautiful syntax highlighting to your Remix app using rehype-prism-plus and Markdown. This setup is ideal for blog posts, documentation, or any content that includes code snippets. The combination of remark, rehype, and Prism.js gives you full control over how your Markdown and code blocks are rendered.

This approach is highly customizable. You can explore more themes, add language-specific plugins, or even customize how code blocks are rendered by tweaking your configuration. Now your Remix blog will not only look great but also provide a better experience for developers reading your code snippets.

Happy coding, and enjoy building with Remix and Markdown!