Rendering Code Blocks in a Next.js and Sanity Project
How to render and copy code blocks using libraries such as @sanity/code-input and react-refractor
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
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="text-dark-textDescription my-8 bg-gray-700 px-4 py-3">
<Refractor language="js" value={value.code} />
<div className="flex justify-end">
<ClipboardIcon
id={`clipboard-icon-${iconId}`}
className="h-6 w-6 cursor-pointer delay-75 hover:text-gray-500"
/>
</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>
)
}
}
}
Update your code as shown below:
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.



