Build a Markdown Editor with Next.js and Storyblok
Storyblok is the first headless CMS that works for developers & marketers alike.
Introduction
One of your options for developing a code-driven website is to use markdowns to create content when creating a blog publication site. In this tutorial, we’d learn to create a markdown editor with Next.js and Storyblok.
What is Markdown?
Markdown is a markup language that can add formatting properties to typically plain text documents. Markdown uses simple syntaxes in the text to effect specific changes to it. These changes could be in headings, bold text, and bullets for creating lists. Its syntax doesn’t require prior programming language experience; it uses symbols to denote specific properties. For example, words can be bold by placing the text between asterisks. Two before and two after, such as **A bold Text**
.
Markdown can be used for writing notes, creating presentations, technical documentation, and blog posts.
You can find the final version of the code used in this tutorial here.
What is Storyblok CMS?
Storyblok is a headless CMS with a visual editor that allows users to create and manage content. The visual editor has a simple user interface to enable users to view a website’s components and manage its content. With this in place, content creators and end-users can manage their application’s content without contacting the site’s developers.
Why use Storyblok?
Below are a few reasons why you should use Storyblok CMS:
- Quickly develop web applications for clients, enabling them to create new content and manage existing content independent of the developer.
- A simple way to understand and integrate a Headless Content Management System.
- Simple User Interface to create and manage content.
- Storyblok CMS is used via simple API requests.
We will build a markdown editor using the Next.js framework. To set it up, navigate to a working directory, clone the GitHub repo and run npm install
to install the necessary dependencies. The previous command will create a project folder with the starter code in the current working directory.
The Editor
component houses the Nav
component and FileList
component. It’s also the component that will contain markdown functionalities. The Nav
component returns a navigation bar with two buttons to “create a new file" {1} and “save” {2}. The FileList
component will display a list of all saved markdown files from Storyblok CMS.
If you run the npm run dev
command in your terminal, you will get a result similar to the image below:
Above is the layout of the application. There is a section to preview created markdown files and another area to enter content. The second section has a toggle button to switch between preview and edit modes.
Adding Markdown Functionality
For the markdown, we will need to take in the user input from textarea
in our Editor.js
file and convert it to markdown to be displayed in the preview
section. To do this, we will first create a state variable to handle input changes for text:
Then we assign this value to the textarea
value property and pass this function to the onChange
event.
We will use the reactMarkdown
, remarkGfm
, and React-syntax-highlighter
npm packages to render markdowns. Since these modules are pre-installed, we need to add imports:
For the preview window, add the code block below:
The ReactMarkdown
component renders whatever text is passed to it as markdown. RemarkGfm
adds support for URLs, strikethroughs, tables, and lists.
To better style the markdown appearance, add the following styles to global.css
:
Now, if we run our application with the npm run dev
command, we can add markdowns in the textarea
and preview it.
In the image above, the markdown entered is rendered and displayed in the preview window. The code block, however, is not properly formatted. To do this, we will use React-syntax-highlighter. We will automatically detect code blocks denoted by ``` followed by language name, this will be rendered following the syntax highlighting style for the language.
With this in place, syntax highlighting will be carried out on code blocks.
When we toggle to the preview window using the preview button, we can view the formatted markdown below:
Setting up Content Structure
With the Markdown Editor built, the next step is to set up the content structure for our application on Storyblok. Navigate in a browser to Storyblok and log in if you have a pre-existing account or otherwise create a new user account.
On the dashboard, click on “Try Storyblok V2” to use the latest version of Storyblok.
A new page opens up similar to the image above. On this page, a custom space Home is created by default. Click on the “Create new” {1} button in the top right corner and create a story.
After creating the story, a new window displays authentication credentials in the visual editor window, alongside a form for adding content. Finally, we will create two fields in the form: a title field of type Text
and a markdown field of type Markdown
.
Click on the save {1} and publish {2} buttons to finalize these changes. If we create an entry in the form as shown below:
Save and publish. There’s a dropdown menu beside the publish button which allows us to view the published data. Creating an API request for the published URL will return the data of the story as JSON. To return all stories in the space, we will use Storyblok dependency.
Connecting the Application to Storyblok
To use Storyblok in our application, we need to install the @storyblok/react
dependency along with axios to instantiate our request:
Then we can add an import for this dependency in our Editor.js
and initialize it using the authentication token.
The above code will return all stories created in our space. We can pass this from Editor.js
to the FileList
component to display the titles.
And in FileList.js
:
Below are the stories in my Storyblok content.
The named attributes of the Stories
are returned by the FileList
component as shown below:
Adding a New File Creation Window
In Editor.js
, we will first create a pop-up window that appears when the create new file
button is clicked to create new files. This window will have an input field for the file's name to be created.
We can view this change in our browser:
Still on the Editor.js
, to toggle the created window, we will create a boolean variable and use the Create file
button to change the value of this button.
Set the create a new file
window to only show if displayWindow
is true:
We can use the create new file
button to set this value to true with the onClick
event handler:
In Nav.js
, we take this prop and use the create new file
button to toggle its value.
For the onClick
event handler, add the display
prop:
To set this value to false, add an onClick
event listener to the display window close button in Editor.js
:
To create a new File functionality, navigate to the Editor.js
component and we will take in the value from the input field using the state variable.
Displaying Markdowns from Saved Files
Aside from displaying the names of the stories from Storyblok in the FileList
component, we can display the data from these stories in the markdown editor. To do this, in Editor.js
we will pass the data from the selected file onClick
:
In File.js
. we can return the values from the selected file:
Now, when any listed item is clicked, the corresponding markdown is displayed. We will also display the current file being edited in the Nav component for ease of use. First, we pass a prop to the Nav
component in Editor.js
:
In Nav.js
we will get the passed data and render it in the navigation bar:
Creating new Stories
To create new stories, in Editor.js,
we will create a function that takes the input from the new file window and pass it in a post request, as shown below:
The authorization token and space id can be obtained from the Storyblok settings. With this in place, we can call this function in the Create File
button in Editor.js
.
Updating a Story
Since the current story’s data is passed to the Nav
component, we need to return this data `onClick` of the save
button. To do this, we will first create a function to update stories in our Editor
Component and pass it from Editor.js
to the Nav
component:
In Nav.js
, we will pass a value from the save
button, which will be the current file being edited.
Deleting a Story
With the above, we can read our stories from Storyblok, create new stories and update them. The final functionality for our markdown editor would be a feature to delete
a selected story. We will build this just like the Save
button functionality. In Nav.js
, we will add a button after the Save
button for the delete functionality:
In Editor.js
we will create a function to function that will make a delete request to Storyblok, with the data passed by the Delete
button:
Above is our delete
request. We just need to pass this from Editor.js
to the Nav
component.
Below is the final look of our application with the delete button: