Post

Rendering Code Blocks in a Next.js and Sanity Project-img

Rendering Code Blocks in a Next.js and Sanity Project

July 16, 2023

Tansel Berkant Oflaz

Tansel Berkant Oflaz

This blog post provides step-by-step instructions on how to render and copy code blocks using libraries such as @sanity/code-input and react-refractor

Next.js

Sanity

Introduction

In this blog post, I will share my journey of implementing code block rendering in a Next.js and Sanity project. Initially, I used to include images instead of actual code blocks in my blog posts. However, in order to make my articles more accessible and developer-friendly, I decided to tackle this challenge. After overcoming various hurdles, I successfully achieved the desired outcome. Now, I want to share the process of how I accomplished it.

Prerequisites

Before diving into the implementation details, make sure you have the following dependencies installed:

  • @sanity/code-input package (version 4.1.1 or higher)
  • react-refractor package
  • @portabletext/react package
  • uuid package

Additionally, ensure that you have a Next.js and Sanity project set up and configured properly.


Step 1: Installing and Configuring @sanity/code-input

To begin, install the @sanity/code-input package by running the following command:

yarn add @sanity/code-input@^4.1.1
  • Next, open the sanity.config.ts file and add the codeInput plugin to the plugins array:
import { codeInput } from '@sanity/code-input';

export default defineConfig({
  // ...
  plugins: [codeInput()],
});

Step 2: Modifying the Schema to Support Code Blocks

In your post.ts schema file, locate the existing defineField block responsible for rendering the body content. Add the following code block definition within the defineArrayMember section:

defineArrayMember({
  type: 'code',
  name: 'myCodeField',
  title: 'Code with all options',
  options: {
    language: 'javascript',
    languageAlternatives: [
      { title: 'Javascript', value: 'javascript' },
      { title: 'TypeScript', value: 'typescript' },
      { title: 'tsx', value: 'tsx' },
    ],
    withFilename: true,
  },
}),

Step 3: Implementing Code Block Rendering in the Frontend

To render the post body, we will be using the PortableText component from the @portabletext/react package. Modify your code as follows:

import { PortableText } from '@portabletext/react';

// ...

<PortableText
  onMissingComponent={false}
  value={post.body}
  components={RichTextComponents}
/>

Step 4: Customizing the Rendering of Code Blocks

In order to customize the rendering of code blocks, we need to define a custom component within the RichTextComponents object. Install the react-refractor package by running:

yarn add react-refractor

Update your code as shown below:

import Refractor from 'react-refractor';
import { v4 as uuid } from 'uuid';

export const RichTextComponents = {
  types: {
    // ...
    myCodeField: ({ value }) => {
      const iconId = uuid();
      return (
        <div className="my-8 bg-gray-700 text-dark-textDescription px-4 py-3">
          <Refractor language="js" value={value.code} />
          <div className="flex justify-end">
            <ClipboardIcon
              id={`clipboard-icon-${iconId}`}
              className="w-6 h-6 cursor-pointer hover:text-gray-500 delay-75"
            />
          </div>
          <script
            dangerouslySetInnerHTML={{
              __html: `
                document.getElementById('clipboard-icon-${iconId}').addEventListener('click', function() {
                  const textToCopy = ${JSON.stringify(value.code)};
                  const textarea = document.createElement('textarea');
                  textarea.value = textToCopy;
                  document.body.appendChild(textarea);
                  textarea.select();
                  document.execCommand('copy');
                  document.body.removeChild(textarea);
                });
              `,
            }}
          />
        </div>
      );
    },
  },
};

Conclusion

By following the steps outlined in this blog post, I successfully integrated code block rendering into my Next.js and Sanity project. I overcame the initial challenge of including images in place of code blocks, and now my blog posts are more accessible and developer-friendly. I hope this step-by-step guide helps you in implementing code block rendering in your own projects.


© 2024 Tansel Berkant Oflaz. All Rights Reserved.