• Home
  • Blog
  • Contact
  • Book a call

© Copyright 2026 | Vladyslav Dihtiarenko | All Rights Reserved

Next.js Server Side Code Highlighting with Prismjs

Mar 5, 2024

•

#next.js

•

3 mins read

If you prefer watching instead of reading, check out this video:

Text Version

In this tutorial I’ll be teaching you how to add that beautiful code highlighting to your Next.js project. We’ll use Prismjs library and handle synthax highlighting on the server side, so the client will receive the highlighted code without flickering and hydration issues, which is a bit trickier. Without further ado, let’s get started.

Setup

So, we’re in VSCode. Here’s a starter code with some boilerplate prepared, I’ll include a repo in the description, but you can use your own project If you want.

Pass code snippet to your JSX

In real projects, you’d probably receive a code snippet as a string from an API. But for now, I’ll use a code from layout.jsx file for demonstration purposes and store it in a variable. Feel free to choose your favorite peace of code to use it throughout the tutorial.

// App.tsx

const code = `import './globals.css'
import { Inter } from 'next/font/google'

const inter = Inter({ subsets: ['latin'] })

export const metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
}

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body className={inter.className}>{children}</body>
    </html>
  )
}`;
//...

Pass the code to your JSX:

<code>{code}</code>

We’ve just rendered the code in our layout.

☝🏻As you probably mentioned, the line breaks are preserved, because the <code> element uses white-space: pre by default. In real world projects, you may receive a string of code with line breaks handled by \n instead.

Setup Prism

Install the library:

npm i prismjs

Import Prism into your component file:

import Prism from "prismjs";

Then, we need to choose a theme. You can go to the prism’s test drive page and choose between all the available themes here and see how it looks. For my taste, I choose “Okaidia” theme.

To add the necessary styles for our theme, we need to import it in that way:

import "prismjs/themes/prism-okaidia.css";

Then, we need to import prism components for all the other languages we need. By default, Prismic imports a very few languages, including html, css and javascript. To add support for JSX, we need to manually import it:

import "prismjs/components/prism-jsx";

Now, It’s time to write a highlight function that will use Prism to perform synthax highlighting. It will receive a code as a string, performs a highlighting and returns an html string. Basically, it just maps through our code string, finds the code elements and wraps them into <span> elements with appropriate CSS classes that colors our code.

const highlight = (code, language = 'markup') => {
  const res = Prism.highlight(code, Prism.languages[language], language);
  return res;
}

// ...

Then, we can perform highlighting inside our JSX. Remember, we’re doing in on the server side, because it’s a React Server Component.


export default function Home() {
  const language = "jsx";
  const highlightedCode = highlight(code, language);
  
  return (
	//...

Remember, that we’ve just returned an html string, not an actual HTMLElement or a collection of HTMLElements. In order to pass it properly, we should use dangerouslySetInnerHTML.

Lastly, we need to add proper CSS classes in this way:

<pre className={`language-${language}`}>
  <code 
		className={`language-${language}`}
		dangerouslySetInnerHTML={{
	    __html: highlightedCode,
	  }}
	></code>
</pre>

Let’s see how our page looks like:

Looks brilliant! However, there’s a scrollbar appeared and we’ve lost our line breaks even we’ve handled it by the white-space property. Because we’ve hard-coded our code snippet, we need to manually handle line breaks:

Optional: security

We’ve used dangerouslySetInnerHTML here which is known as an unsecure method, because it is vulnerable to XSS attacks. If you’re in a safe environment, you can skip this step. But for an extra security level here, we’ll use a DOMPurify library to sanitize our html string to preventively remove any XSS attacks.

💡DOMPurify will strip out everything that contains dangerous HTML and thereby prevent XSS attacks and other nastiness.

You may have noticed that the library is DOM-only, so it works only on the client side code. But in our Next.js component, we’re working with the server code, i.e. there’s no DOM.

That’s why we need isomorphic-dompurify. The library makes it possible to seamlessly use DOMPurify on server and client in the same way.

import DOMPurify from "isomorphic-dompurify";

// ...

dangerouslySetInnerHTML={{
  __html: DOMPurify.sanitize(highlightedCode),
}}

Extra tip:

💡You may ocasionally pass a language string to .highlight function that Prism doesn’t support. In this case, it might throw an error. To address any potential function execution errors, wrap the .highlight() function in try/catch block and return a default code string as a fallback.