Rendering Code Blocks in a Next.js and Sanity Project
July 16, 2023
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.