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

Add a headless CMS to React in 5 minutes

Try Storyblok

Storyblok is the first headless CMS that works for developers & marketers alike.

In this short tutorial, we’ll look at how we can integrate Storyblok into a React application with the help of the new @storyblok/react, the official Storyblok React SDK. We will see how we get the data from Storyblok and how we enable Storyblok Bridge to preview live changes in the Visual Editor.

HINT:

You can find the final code for this tutorial in this repo.

Section titled Requirements Requirements


Here are a few requirements to follow this tutorial:

  • Basic understanding of React and Javascript.
  • Node.js LTS version (npm or yarn installed).
  • A Storyblok App account for creating project in Storyblok.

Section titled Project Setup Project Setup

Start by creating a new React Project.

        
      npx create-react-app storyblok-react-5-min-tutorial

    

Then install the package @storyblok/react. This is the main package needed for this tutorial.

        
      cd storyblok-react-5-min-tutorial
npm install @storyblok/react
# yarn add @storyblok/react
    

The package @storyblok/react allows us to set up everything. It helps us get the data from Storyblok, loads Storyblok Bridge for real-time visual updates, and provides us with a storyblokEditable function to link editable components to the Storyblok Visual Editor.

Once the packages are installed we can start our development server.

        
      npm run start
# yarn start
    

It should open a tab in the browser automatically with the url http://localhost:3000, or we can manually go to the url after the project starts running. You should see this screen.

React App Landing Page

React App Landing Page

If you’re using Storyblok V2, you will need to setup the dev server with an HTTPS proxy. We will use port 3010, so the url to access the website will become https://localhost:3010/

HINT:

If you don't know how to setup an HTTPS proxy on macOS, read this guide.

Section titled Space Configuration Space Configuration

Now create a new space in the Storyblok App by clicking "+ Create New". Select the first option to start from scratch {1} and then give it a name {2}.

Create New Space
1
2

New Space Creation

We will get a space with sample content already created for us. After this, we need to configure our Visual Editor to get the live preview of our website. For this, go to Settings {1} > Visual Editor {2}, and set the Location (default environment) {3} to https://localhost:3010/.

Visual Editor Location
1
2
3

Adding Location to Visual Editor

Now go to the Home Page from the Content section. You should already see our React app. Click on the Entry Configuration {1} and set the Real Path {2} to “/”. This will be useful later when we get the data depending upon the slug.

Visual Editor
1
2

Visual Editor

We can also see some of the components created for us on the right hand side, which we will create later in our app.

Section titled Connect React to Storyblok Connect React to Storyblok

Connect the React Application to Storyblok with the help of the SDK. We use two things from the package in the index.js file storyblokInit and apiPlugin. We need to add the following code to the index.js file.

index.js
        
      ...

import { storyblokInit, apiPlugin } from "@storyblok/react";

storyblokInit({
  accessToken: "YOUR_PREVIEW_TOKEN",
  use: [apiPlugin],
  components: {}
});

...
    

Section titled Setting the correct region Setting the correct region

Depending on whether your space was created in the EU, the US, Australia, Canada, or China, you may need to set the region parameter of the API accordingly:

  • eu (default): For spaces created in the EU
  • us: For spaces created in the US
  • ap: For spaces created in Australia
  • ca: For spaces created in Canada
  • cn: For spaces created in China

Here's an example for a space created in the US:

        
      apiOptions: {
  region: "us",
},
    
WARN:

Note: For spaces created in any region other than the EU, the region parameter must be specified.

storyblokInit allows us to set up the connection with the space and also loads the Storyblok Bridge, which helps us to see the real-time changes when editing the content. The apiPlugin here helps us get the data. If you don't want to use apiPlugin, you can use your preferred method or function to fetch your data.

We have a components key here to declare all the React components that we need to create, according to the ones we have in our space. These components are dynamically rendered with the StoryblokComponent which we will see in a bit. We need to keep the names the same at both places for it to work while creating the components.

Get the preview token and replace the value at accessToken. To do this, go to Settings {1} > Access Tokens {2}, and copy the Preview access token.

Space Access Tokens
1
2

Getting Access Token

To get data and dynamically load it, change the code of app.js to the following:

App.js
        
      import { useStoryblok, StoryblokComponent } from "@storyblok/react";

function App() {

  let slug =
    window.location.pathname === "/"
      ? "home"
      : window.location.pathname.replace("/", "");

  const story = useStoryblok(slug, { version: "draft" });
  if (!story || !story.content) {
    return <div>Loading...</div>;
  }

  return <StoryblokComponent blok={story.content} />;
}

export default App;
    

Here we use useStoryblok after getting the slug, which helps us get the new story every time we change anything in the editor. It has three parameters, the first one being the slug. The second parameter is the apiOptions where we have all of the API options for getting the data, and the third one is the bridgeOptions which is optional for configuring the bridge.

useStoryblok Params
ParameterDescription
slug*The first parameter of type string. Slug of the required story
apiOptions*The second parameter of type object, for configuring the API options.
bridgeOptionsThis is an optional parameter of type object, for customizing the bridge options.

We also see StoryblokComponent in action here. It can be used anywhere in the code to render the React components we created according to our space. We can pass the content for a story with blok prop. For this to work, it’s important to list them in storyblokInit.

In Storyblok, the content is structured as components. As we already have some components created in our space, let’s create those in our React app. This allows us to reuse the components dynamically.

Section titled Creating Components Creating Components

When we create a new space, the default components are: Page, Teaser, Grid and Feature. Now create the mentioned components in our app.

In the components folder:

components/Page.js
        
      import { StoryblokComponent, storyblokEditable } from "@storyblok/react";
 
const Page = ({ blok }) => (
  <main {...storyblokEditable(blok)} className="px-4">
    {blok.body
      ? blok.body.map((blok) => (
          <StoryblokComponent blok={blok} key={blok._uid} />
        ))
      : null}
  </main>
);
 
export default Page;
    

We also use a storyblokEditable function from the SDK. It allows us to mark the react component editable in the Visual Editor. With the help of this function, we can click the components in the Visual Editor and easily edit them. Hence we will use this for all the Storyblok components.

components/Teaser.js
        
      import { storyblokEditable } from "@storyblok/react";

const Teaser = ({ blok }) => {
  return (
    <h2 className="py-32 text-6xl text-[#50b0ae] font-bold text-center" {...storyblokEditable(blok)}>
      {blok.headline}
    </h2>
  );
};

export default Teaser;
    
components/Grid.js
        
      import { StoryblokComponent, storyblokEditable } from "@storyblok/react";

const Grid = ({ blok }) => {
  return (
    <div
      {...storyblokEditable(blok)}
      className="container mx-auto grid md:grid-cols-3 gap-12 my-12 place-items-center"
    >
      {blok.columns.map((blok) => (
        <StoryblokComponent blok={blok} key={blok._uid} />
      ))}
    </div>
  );
};

export default Grid;
    
components/Feature.js
        
      import { storyblokEditable } from "@storyblok/react";

const Feature = ({ blok }) => (
  <div
    className="w-full p-12 bg-[#f7f6fd] rounded-[5px] text-center column feature"
    {...storyblokEditable(blok)}
  >
    <h3 className="text-2xl text-[#1d243d] font-bold">{blok.name}</h3>
  </div>
);

export default Feature;
    

Now, just add these components in storyblokInit. It should look something like this:

index.js
        
      import React from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App";
import { storyblokInit, apiPlugin } from "@storyblok/react";

import Page from "./components/Page";
import Teaser from "./components/Teaser";
import Grid from "./components/Grid";
import Feature from "./components/Feature";

storyblokInit({
  accessToken: "YOUR_ACCESS_TOKEN",
  use: [apiPlugin],
  components: {
    page: Page,
    teaser: Teaser,
    grid: Grid,
    feature: Feature,
  },

  apiOptions: {
    // for spaces located in the US or China:
    // region: "us" or "cn", // you need to specify the region
    region: ''
  }
});
    

And that’s all! You should be able to see your content in the Visual Editor, now that you’ve unlocked the power of live editing. You can start playing with the content and see live changes. It should look something like this:

Live Editing

Live Editing

Section titled Wrapping Up Wrapping Up

In this tutorial, you saw an overview of how to create and integrate a React Application with Storyblok with the help of the official React SDK. Additionally, you learned how to use the data and enable the real-time Visual Editor.

Authors

Chakit Arora

Chakit Arora

Chakit is a Full Stack Developer based in India, he is passionate about the web and likes to be involved in the community. He is a Twitter space host, who likes to talk and write about technology. He is always excited to try out new technologies and frameworks. He works as a Developer Relations Engineer at Storyblok.

Fortune Ikechi

Fortune Ikechi

Fortune Ikechi is a Software Engineer proficient with MERN stack and lover of Golang. Currently a Developer Relations Engineer at Storyblok, Fortune is passionate about community building and open source.