← Back to blog

How to Add Beautiful, Copyable Code Blocks to a Sanity Blog

Learn how to add code blocks, display code cleanly on a website, and style your snippets with syntax highlighting & copy to clipboard functionality within Sanity blog posts.

Sanity, Next.js, React, Web Development, Code Blocks

Code blocks make technical articles easier to read and allow readers to copy code directly from your website.

This guide shows the basic setup from start to finish.

1. Install the code block package.

In your Next.js project, install the syntax-highlighting package:

yaml
npm install prism-react-renderer

This package highlights code based on the programming language.

2. Add a code field to your Sanity schema

Open your blog post schema:

text
sanity/schemas/post.ts

Find the body field.

Instead of having only:

typescript
defineField({
  name: 'body',
  title: 'Body',
  type: 'array',
  of: [
    {
      type: 'block',
    },
  ],
}),

add a code block to the of array:

typescript
defineField({
  name: 'body',
  title: 'Body',
  type: 'array',
  of: [
    {
      type: 'block',
    },
    {
      type: 'code',
      options: {
        language: 'javascript',
        languageAlternatives: [
          { title: 'JavaScript', value: 'javascript' },
          { title: 'TypeScript', value: 'typescript' },
          { title: 'HTML', value: 'html' },
          { title: 'CSS', value: 'css' },
          { title: 'JSON', value: 'json' },
          { title: 'Bash', value: 'bash' },
          { title: 'Python', value: 'python' },
        ],
      },
    },
  ],
}),

The important part is that your body can now contain two types of content:

text
Normal text
+
Code blocks

3. Restart your development server

After changing the Sanity schema, stop your development server:

text
Ctrl + C

Then start it again:

yaml
npm run dev

Open your Sanity Studio:

text
http://localhost:3000/studio

Create or open a blog post.

When you add content to the Body, you should now have the ability to insert a code block.

4. Add code to your blog post

Inside Sanity Studio, write your article normally.

For example:

React is a JavaScript library used to build user interfaces.

Then insert a Code block.

Choose:

text
JavaScript

and enter:

javascript
const greeting = "Hello World";

console.log(greeting);

You can then continue writing normal text underneath the code.

Your article can therefore look like:

text
Heading

Paragraph explaining the code.

CODE BLOCK

Paragraph explaining what happened.

Another CODE BLOCK

Conclusion

5. Tell Next.js how to display the code

This is the part that makes the code look good on your actual website.

You already have this in your blog post:

typescript
<PortableText value={post.body} />

Instead of letting PortableText use its default rendering, give it a custom components configuration.

For example:

typescript
const portableTextComponents = {
  types: {
    code: ({ value }: any) => (
      <pre className="my-6 overflow-x-auto rounded-xl bg-black p-5 text-sm text-white">
        <code>{value.code}</code>
      </pre>
    ),
  },
};

Then change:

typescript
<PortableText value={post.body} />

to:

typescript
<PortableText
  value={post.body}
  components={portableTextComponents}
/>

Now your Sanity code blocks will appear as styled code blocks on your website.

6. Add a Copy button
You can make the code block even better by allowing readers to copy the code.

Create:

text
src/components/CodeBlock.tsx

Add:

typescript
"use client";

import { useState } from "react";

interface CodeBlockProps {
  code: string;
}

export default function CodeBlock({ code }: CodeBlockProps) {
  const [copied, setCopied] = useState(false);

  async function copyCode() {
    await navigator.clipboard.writeText(code);

    setCopied(true);

    setTimeout(() => {
      setCopied(false);
    }, 2000);
  }

  return (
    <div className="relative my-6 overflow-hidden rounded-xl bg-black">
      <button
        onClick={copyCode}
        className="absolute right-3 top-3 rounded-md border border-white/20 px-3 py-1.5 text-sm text-white"
      >
        {copied ? "Copied!" : "Copy"}
      </button>

      <pre className="overflow-x-auto p-5 pt-14 text-sm text-white">
        <code>{code}</code>
      </pre>
    </div>
  );
}

7. Use the CodeBlock inside Portable Text

Go back to:

text
src/app/(site)/blog/[slug]/page.tsx

Import the Component:

typescript
import CodeBlock from "@/components/CodeBlock";

Then create your Portable Text configuration:

typescript
const portableTextComponents = {
  types: {
    code: ({ value }: any) => (
      <CodeBlock code={value.code} />
    ),
  },
};

Then use it:

typescript
<PortableText
  value={post.body}
  components={portableTextComponents}
/>

That's it.

Your Sanity code block now becomes the custom CodeBlock component on your website.

8. What the reader sees

When you write this in sanity:

javascript
const name = "Michael";

console.log(name);

Your website can display something like this:

text
┌──────────────────────────────────────────┐
│                              [ Copy ]    │
│                                          │
│ const name = "Michael";                  │
│                                          │
│ console.log(name);                       │
│                                          │
└──────────────────────────────────────────┘

When the reader clicks Copy, the code is copied to their clipboard.

9. Adding different programming languages

When creating a code block in Sanity, select the appropriate language.

For example:

Javascript

javascript
const message = "Hello World";
console.log(message);

Typescript

typescript
interface User {
  name: string;
  age: number;
}

Python

python
name = "Michael"

print(name)

Bash

yaml
npm install
npm run dev

JSON

json
{
  "name": "Michael",
  "role": "Software Engineer"
}

The important thing is that Sanity stores the code and its language, while your Next.js application controls how that code is displayed.

Think of the whole system like this:

text
Write article
      ↓
Open Sanity Studio
      ↓
Add normal text
      ↓
Insert Code block
      ↓
Choose language
      ↓
Write code
      ↓
Publish
      ↓
Next.js receives the content
      ↓
PortableText detects the code block
      ↓
CodeBlock component displays it
      ↓
Reader sees styled code + Copy button