In this tutorial, you will learn how to render content using Strapi's Rich Text Block Editor in a Next.js project.
Instead of building your project from scratch, I already have a repo with the example.
To save time, you will walk you through the example project and explain all the important details so you can get started with the new block renderer in your project.
You can find the example project here.
Start by cloning the repo with the following command.
Ensure you have Github CLI installed.
gh repo clone PaulBratslavsky/strapi-block-renderer-test
Once you have the project cloned, run the following commands to set up all the project dependencies.
cd strapi-block-renderer-test
yarn setup
🖐️ NOTE: You might need to run
yarn install
for the above command to work.
Once all the dependencies are installed, you need to add a .env
file inside your Strapi project. Navigate to the backend
folder, create a new .env
file, and add the following:
1HOST=0.0.0.0
2PORT=1337
3APP_KEYS=wXYvvOuO1EkHdx649y6VSw==,ybhl4JrYJCywPzD9/VCCHA==,ny2t0th9YSjS4CboaL5gaw==,4QqGB4RyQfuE/2QraXLUaw==
4API_TOKEN_SALT=ZZr3P8+Wb32+onN+nqki2A==
5ADMIN_JWT_SECRET=FuI/5Q6dpK3WIrmQjgy9RA==
6TRANSFER_TOKEN_SALT=sCUHUXnyxPfDyDtpNBy9Yw==
7JWT_SECRET=BcnO4bwwIbp3XwyVnDONpQ==
Once that is done. You will have to seed your dummy data so you have something to work with.
Change directory to the root of your project and run the following command.
yarn seed
yarn seed
yarn run v1.22.19**
$ cd backend && yarn strapi import -f ../seed-data.tar.gz
$ strapi import -f ../seed-data.tar.gz
? The import will delete your existing data! Are you sure you want to proceed?(y/N)
You will see the following message; just go ahead and click yes.
Once everything is done, you can start both frontend and backend projects by running the following command.
yarn dev
Your Strapi project will start on http://localhost:1337/admin
go ahead and create your first admin user.
Once done, you will be greeted with the dashboard.
If you navigate to Content Manager -> Note, you will see us using the new Strapi's Rich Text Editor.
You can find it as one of the options when building your collection type.
And finally open tour frontend project in your browser by going to http://localhost:3000
and you will seeyour article being displayed.
Now that your project is working. Review the implementation details in the code.
Go ahead and open your project in Vs Code if you haven't already done so. And take a look at the following file found in frontend/src/app/page.tsx
page.tsx
1import { type BlocksContent } from "@strapi/blocks-react-renderer";
2import BlockRendererClient from "./BlockRendererClient";
3
4async function getStrapiData() {
5 const res = await fetch("http://localhost:1337/api/notes");
6 const data = await res.json();
7 return data;
8}
9
10export default async function Home() {
11 const { data } = await getStrapiData();
12
13 const content: BlocksContent = data[0].content;
14
15 return (
16 <main className="max-w-[980px] mx-auto my-36">
17 <h1>{data[0].title}</h1>
18 <BlockRendererClient content={content} />
19 </main>
20 );
21}
In the code above. In Next.js. This defaults to RSC (React Server Component), which is why you are able to fetch the data directly via the getStrapiData()
function, which is pretty cool.
1async function getStrapiData() {
2 const res = await fetch("http://localhost:1337/api/notes");
3 const data = await res.json();
4 return data;
5}
You can call it from your component.
1export default async function Home() {
2 const { data } = await getStrapiData();
3
4 // the rest of the code
5 ...
6}
Once you get the data, you save it to a content
variable and pass it to your BlockRendererClient
component.
1export default async function Home() {
2 const { data } = await getStrapiData();
3 const content: BlocksContent = data[0].content;
4
5 // the rest of the code
6 ...
7}
Before you take a look at the BlockRendererClient
component, here is a brief note on Next.js 14, which can be learned here
In short, Strapi's BlocksRenderer component relies on client-side javascript.
That is why you must wrap it inside your BlockRendererClient and use the "use client" directive at the top of the page.
You can find the implementation of your BlockRenderer inside the /frontend/src/app/BlockRendererClient.tsx
file.
BlockRendererClient.tsx
1"use client";
2import Image from "next/image";
3
4import {
5 BlocksRenderer,
6 type BlocksContent,
7} from "@strapi/blocks-react-renderer";
8
9export default function BlockRendererClient({
10 content,
11}: {
12 readonly content: BlocksContent;
13}) {
14 if (!content) return null;
15 return (
16 <BlocksRenderer
17 content={content}
18 blocks={{
19 image: ({ image }) => {
20 console.log(image);
21 return (
22 <Image
23 src={image.url}
24 width={image.width}
25 height={image.height}
26 alt={image.alternativeText || ""}
27 />
28 );
29 },
30 }}
31 />
32 );
33}
You can read more about the BlockRenderer here to get all the details, steps, and outlines on how to install and set it up in your project.
But you will learn the basics here.
You already have it installed, but if you were to install it in your own project, you would do it with the following command.
yarn add @strapi/blocks-react-renderer
For straight-forward implementation, all you would need to do is just import your component and use it by passing in the block data that you are getting from your API call.
1"use client";
2import {
3 BlocksRenderer,
4 type BlocksContent,
5} from "@strapi/blocks-react-renderer";
6
7export default function BlockRendererClient({
8 content,
9}: {
10 readonly content: BlocksContent;
11}) {
12 if (!content) return null;
13 return <BlocksRenderer content={content} />;
14}
But you can overwrite the default blocks.
In the example below, you will take a look at how you can replace the default with using Next.js Image component.
You can learn more about all the other options here.
But here are all the options available to you for blocks props:
level
)format
)plainText
)image
)url
)You are going to modify your code with the following.
1<BlocksRenderer
2 content={content}
3 blocks={{
4 image: ({ image }) => {
5 console.log(image);
6 return (
7 <Image
8 src={image.url}
9 width={image.width}
10 height={image.height}
11 alt={image.alternativeText || ""}
12 />
13 );
14 },
15 }}
16/>
Inside the BlockRenderer, you are passing an object where you are overwriting the image block with your custom Next.js Image component.
cta title="See Strapi in action with an interactive demo" text="Explore Strapi in an instant, hands-on demo set up just for you." buttontext="Access Live Demo!" buttonlink="https://strapi.io/demo">
In this article, you went over an example project that covers how to use the new Strapi's Rich Text Editor component.
You can also check out the following video here that walks through all the steps.
Thank you for checking out this article, and see you in the next one.
If you have any questions about Strapi 5 or just would like to stop by and say hi, you can join us at Strapi's Discord Open Office Hours Monday through Friday at 12:30 pm - 1:30 pm CST: Strapi Discord Open Office Hours
Theodore is a Technical Writer and a full-stack software developer. He loves writing technical articles, building solutions, and sharing his expertise.