Almost EVERYONE who tried headless systems said they saw benefits. Download the state of CMS now!

Storyblok now on AWS Marketplace: Read more

O’Reilly Report: Decoupled Applications and Composable Web Architectures - Download Now

Empower your teams & get a 582% ROI: See Storyblok's CMS in action

Skip to main content

The Richtext field

Storyblok comes with a powerful Richtext editor that saves your content in a structured JSON format. You can customize the toolbar for each field individually and even let the user insert Storyblok blocks. If you have written your content in Markdown you have the possibility to import it using the toolbar button "Paste from Markdown".

Richtext editor of Storyblok

Richtext editor of Storyblok

Configure Storyblok's Richtext editor

Customize the Richtext editor of Storyblok

Toolbar items
This option lets you define the toolbar items that are available for the user.

Allows only specific components to be inserted
This option lets you define the components that can be inserted by the "Add block" toolbar button.

Allow links to be open in a new tab
This option lets you set links to be open in a new tab on the link modal.

Enable custom attributes for links
This option lets you set custom attributes for your links.

Section titled How to render Richtext data to HTML? How to render Richtext data to HTML?

To render the content of the Richtext field our SDKs come with a render function.

Section titled Javascript SDK Javascript SDK

You can easily render Richtext by using the renderRichText function that comes with @storyblok/js:

        
      import { renderRichText } from "@storyblok/js";

const renderedRichText = renderRichText(blok.richtext);
    

You can set a custom Schema and component resolver globally at init time by using the richText init option:

        
      import { RichTextSchema, storyblokInit } from "@storyblok/js";
import cloneDeep from "clone-deep";

const mySchema = cloneDeep(RichTextSchema); 
// you can make a copy of the default RichTextSchema
// ... and edit the nodes and marks, or add your own.
// Check the base RichTextSchema source here:
//https://github.com/storyblok/storyblok-js-client/blob/main/src/schema.ts

storyblokInit({
  accessToken: "<your-token>",
  richText: {
    schema: mySchema,
    resolver: (component, blok) => {
      switch (component) {
        case "my-custom-component":
          return `<div class="my-component-class">${blok.text}</div>`;
        default:
          return "Resolver not defined";
      }
    },
  },
});
    

You can also set a custom Schema and component resolver only once by passing the options as the second parameter to renderRichText function:

        
      import { renderRichText } from "@storyblok/js";

renderRichText(blok.richTextField, {
  schema: mySchema,
  resolver: (component, blok) => {
    switch (component) {
      case "my-custom-component":
        return `<div class="my-component-class">${blok.text}</div>`;
        break;
      default:
        return `Component ${component} not found`;
    }
  },
});
    

If you are using any javascript framework you can check our SDK documentation below.

Section titled Ruby Client Ruby Client

Following is an example of rendering a Richtext field with the Storyblok Ruby client.

        
      client = Storyblok::Client.new(token: 'YOUR_TOKEN')
client.render(data.richtext_field)
# Returns a html string
    

If you want to render inline components you need to define a component resolver function like the following:

        
      # Option 1: Define the resolver when initializing
client = Storyblok::Client.new(
  component_resolver: ->(component, data) => {
    case component
    when 'button'
      "<button>#{data['text']}</button>"
    when 'your_custom_component'
      "<div class="welcome">#{data['welcome_text']}</div>"
    end
  }
)
 
# Option 2: Define the resolver afterwards
client.set_component_resolver(->(component, data) {
  "#{component}"
})
    

Section titled Python Client Python Client

This example shows how to use the pip package storyblok-richtext.

First, install it via the following command:

        
      pip install storyblok-richtext
    

Then render a Richtext field like this:

        
      from storyblok_richtext import Richtext
 
resolver = Richtext()
 
data = # get the data from the storyblok api
resolver.render(data.story.your_field)
    

Section titled PHP Client PHP Client

This example shows how to use the composer package storyblok/richtext-resolver.

First, install it via the following command:

        
      composer require storyblok/richtext-resolver dev-master
    

Then render a Richtext field like this:

        
      <?php
 
require __DIR__ . '/vendor/autoload.php';
 
use Storyblok\RichtextRender\Resolver;
 
$resolver = new Resolver();
 
$json = json_decode(file_get_contents('https://api.storyblok.com/v1/cdn/stories/tp/gatsby-multilanguage-website-tutorial?version=published&token=AX6tIYuiZIoGnDAr5wRZFwtt'), true);
$data = $json['story']['content']['body'][0]['richtext'];
 
echo $resolver->render($data);
    

Section titled Components inside the Richtext field Components inside the Richtext field

What makes the Richtext field really powerful is the possibility to insert components. This lets you extend the functionality of the editor to render custom elements.

To render these components be sure to define a component resolver like shown in the section "How to render Richtext data to HTML" above.

Usually you don't want that your users insert all types of components in the Richtext field so you can restrict the type with the option "Allow only specific components to be inserted".

Richtext editor with inline components inside

Richtext editor with inline components inside

Section titled Migration from the Markdown field Migration from the Markdown field

Currently you have two options to migrate a Markdown field to Richtext field.

  1. Create a new field in the schema of your component, copy the content of the Markdown field and insert it with the "Paste from Markdown" button to the new field.
  2. Change the fieldtype of the Markdown field to a Richtext field. This will not immediately change Markdown to the Richtext format so you will need to include a check for the type in your code:
        
      if (typeof data.markdown_field === 'string') {
  return marked(data.markdown_field)
} else {
  return Storyblok.richTextResolver.render(data.markdown_field)
}
    
INFO:

Tech stack of RT Editor

Our Richtext editor is built using TipTap Richtext editor. Check out their documentation if you want to build your own version of the Richtext editor field.