In this tutorial, I will show you how to render content using Strapi's new Rich Text Block Editor in a Next.js project.
Instead of building our project from scratch, I already have a repo with the example.
To save time, I 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
Let's start by cloning the repo with the following command.
gh repo clone PaulBratslavsky/strapi-block-renderer-test
Once we have I project cloned, let's run the following commands to set up all the project dependencies.
1 cd strapi-block-renderer-test
2 yarn setup
Once all the dependencies are installed we need to add a .env
file inside our Strapi project. Let's navigate to the backend
folder and create a new .env
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. Let's seed our dummy data so we 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, we 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.
![Screenshot 2024-01-28 at 4.43.49 PM.png]
And finally open tour frontend project in your browser by going to http://localhost:3000
and you will see our article being displayed.
Now that our project is working. Let's review the implementation details in code.
Go ahead and open your project in vs code if you haven't already. And lets that 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 const content: BlocksContent = data[0].attributes.content;
13
14 return (
15 <main className="max-w-[980px] mx-auto my-36">
16 <h1>{data[0].attributes.title}</h1>
17 <BlockRendererClient content={content} />
18 </main>
19 );
20}
In the code above. In Next JS. This defaults to RSC (React Server Component) that is why we are able to fetch the data directly via 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}
And we are able to call it from our component.
1export default async function Home() {
2 const { data } = await getStrapiData();
3 // the rest of the code
4}
Once we get the data, we save it to a content
variable and pass to our BlockRendererClient component.
1export default async function Home() {
2 const { data } = await getStrapiData();
3 const content: BlocksContent = data[0].attributes.content;
4 // the rest of the code
5}
Before we take a look at BlockRendererClient Component a brief note on Next JS 14
You can learn more here
But in short. Strapi's BlocksRenderer component relies on client side javascript. That is why we must wrap it inside our BlockRendererClient and use use client
directive at the top of the page.
You can find the implementation of our 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 detail step and outline on how to install and set it up in your project.
But I will cover the basic here.
We 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 simple 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 if you wanted to overwrite the default blocks, you can do so. In the example below, we will take a look how we can replace the default with using Next Image component.
You can learn more about all the other options here
But here is all the options available to you for blocks prop
level
)format
)plainText
)image
)url
)We are going to modify our 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 we are passing an object where we are overwriting the image block with our custom Next JS Image component.
In this article, we 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 our this article and I will see you in the next one.
Reminder, I hang out in Strapi's Open Office Monday through Friday at 12:30 PM CST. Stop on by with questions or just to hang out.