Simply copy and paste the following command line in your terminal to create your first Strapi project.
npx create-strapi-app
my-project --quickstart
Notion is a popular note-taking tool loved by many for its responsiveness and dynamic features. Its collaborative setting allows teams around the world to document, share, and communicate easily. On top of that, the component-like nature of Notion content not only supports many types of formats (images, links, tables, etc.), but it makes writing and editing a breeze.
Strapi is the leading open-source content management system (CMS) and will act as our content hub for this project. Not only is it fast, but Strapi is also very developer-friendly. You can consume the Strapi API from any client using REST or GraphQL. Strapi offers many integrations, along with ample documentation on how to integrate it with all the major frontend libraries such as Next.js, React, Vue, Gatsby, and others.
This two-part tutorial series will walk you through the creation of a Notion clone with Strapi and Next.js. In this article, you will get familiar with Strapi and its admin interface. You will also learn about the GraphQL playground and how to create queries and mutations.
In order to create your Notion clone, you will need two important components: a Next.js client and a Strapi server.
To start with, you will need a Strapi backend. As mentioned above, Strapi will act as your content hub. This will not only allow you to create data structures, but will also store your data. For this project, you will have two kinds of data:
Pages
Content blocks
By using blocks, you can replicate the way Notion creates content. Every block will have raw HTML stored in it that, when fetched, will be rendered on the client. As for the pages, they will have a title and a list of blocks that belong to them.
You will be interacting with this data thanks to GraphQL, which you will install with your Strapi backend. Once done, you will design queries and mutations that will allow you to create, update, and delete content through your new API.
Finally, there is the Next.js client which will reproduce some of the functionalities of Notion. Just like the popular note-taking application, this frontend will have a few features such as creating pages, but also the ability to create blocks of content on your page. You will be using an HTML editor to recreate a rich but easy-to-use editing experience.
The project will also take advantage of Next.js static and server-side rendering by setting a static route for your list of pages but dynamic routes for your single page. Of course, you will also be setting up the routing between them. Finally, we will use the library graphql-hooks
to create a GraphQL client, which will allow you to connect to your Strapi backend and retrieve, save, or update your data.
This section will walk you through a step-by-step guide in building the clone:
To begin, you’ll get started by setting up your Strapi backend.
First, you’ll need to have npm and Node.js installed. If you don’t have them already, click here for the instructions.
Now you can move on to creating a Strapi server.
1
2
3
4
5
npx create-strapi-app strapi-backend --quickstart
# or
yarn create strapi-app strapi-backend --quickstart
When this is done, a tab will open and you will be prompted to create your first administrator. After filling out your information and clicking save, you will gain access to the admin panel.
You currently have an empty project. In the admin panel, you can create your data structure for your future data entries. Strapi calls those data structures collections
. For this project, you will need two kinds of collections:
Content block
Page
Content Block
collection.On the left-hand side, head over to Content-Type Builder and click Create new collection type.
Add “Content Block” for the display name and click continue.
Under select a field for your collection type, choose Text.
In the Add new text field modal, enter “content” for the Name and choose Long text.
Click Finish and then Save.
Note: The reason you will choose Text here is in order to take advantage of the vast choices in terms of HTML editors for React. As a result, you will be storing raw HTML for your content. It is, however, interesting to note that Strapi does have a Rich Text field which supports Markdown. This can be very helpful for some developers used to writing this way.
Page
collection.Click on Create new collection type.
Fill out “page” for the display name and click continue.
Select Text and name the field “title”.
Add a second field, and this time, select Relation.
Note: Strapi offers many different kinds of relationships depending on your needs. Whether it’s one-to-one, one-to-many, many-to-one or many-to-many, you will find what you need.
Select the third option (“Page belongs to many Content Blocks”).
Click Finish.
Note: This will create a content_blocks
field on pages with an array of content blocks IDs, but it will also create a page field on the content block to save the page ID.
Now that your collections are set up, you are almost ready to set up GraphQL. But before you do so, you need to make your data accessible. This means that you need to allow your data to be accessed and retrieved through your GraphQL API. The steps to do so are:
Head to General > Settings.
Under Users & Permissions Plugin, select Roles.
Click on Public.
Click on the Select all for pages and content-block.
Click Save.
Now that your data is accessible through an endpoint, it’s time to set up GraphQL.
If your Strapi server is still running, stop it with Ctrl+C. In the terminal, run the command:
1
2
3
4
5
npm run strapi install graphql
# or
yarn strapi install graphql
Then you can start up your server again with yarn develop
or npm develop
.
Now that your Strapi backend is set up with GraphQL, it’s time to play with your data a bit. You can access the GraphQL playground and try to create and retrieve some data.
If you are unfamiliar with this technology, GraphQL uses queries and mutations to interact with data. Queries
allow you to retrieve data by asking specifically for what you want. Mutations
, on the other hand, let you modify data whether by creating, updating, or deleting it. Do not hesitate to check out the GraphQL documentation for more explanation.
Next, create your first query in the GraphQL playground. In a new tab, input the type (query or mutation). Because you’ll want to start by retrieving all the pages, you should choose a query and then enter getAllPages
to name your function.
Once that is done, specify the collection you want to retrieve (i.e pages
) and the fields from that collection you want (id
, title
).
1
2
3
4
5
6
7
8
9
10
11
query getAllPages {
pages {
id,
title
}
}
Run it and see the response displayed in the right hand-side of the playground.
If you want to retrieve the related content—say, all the content blocks—add content_blocks
and specify which fields in this collection you want to retrieve.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
query getAllPages {
pages {
id,
title,
content_blocks {
id,
content
}
}
}
Here are some more queries and mutations for you to try out:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mutation createPage {
createPage(input: { data: { title: "New Page"}}) {
page {
id,
title
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
query getOnePage{
page(id: 1) {
id,
title,
content_blocks {
id,
content
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
mutation updatePage {
updatePage(input: {
where: { id: 1 }
data: {
title: "New Title"
}
}) {
page {
id,
title
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mutation deletePage {
deletePage(input: {
where: { id: 2 }
}) {
page {
id,
title
}
}
}
Try to create some data and see it appear in your Strapi admin panel.
In this article, you learned how to set up a Strapi backend. You did so by first creating a Strapi project, setting up your administrator, and installing GraphQL.
When that was done, you discovered how to create collections in the Strapi admin dashboard. You created two collections, for pages and content blocks, and added the required fields for each. You also set up a relationship between pages and content blocks so that pages would have a list of blocks that belong to them, and blocks would have a record of which page they belong to.
You also learned how permissions worked and edited them so that your data could be accessible through the GraphQL API.
To finish, you interacted with the GraphQL playground and learned how to create queries and mutations.
In part 2, we will continue this tutorial and you will create a Next.js client to consume your GraphQL API.
Marie Starck is a full-stack software developer. She loves frontend technologies such as React. In her free time, she also writes tech tutorials. if she could, she would get paid in chocolate bars.