Storyblok
Search Storyblok's Documentation
  1. Integrate React with Storyblok

Integrate React with Storyblok

Use Storyblok to manage the content of your React application.

This guide has been tested with the following package versions:

  • react@19.1.0
  • react-router@7.5.2
  • @storyblok/react@4.6.0
  • Node.js v22.13.0

Setup

Create a new React project in a few simple steps by following the Vite guide documentation.

Kick off this process by running this command:

npm create vite@latest my-react-app -- --template react

If you don’t already have a Storyblok space, create a starter space at app.storyblok.com, it already comes with initial content and component used in the first part of this guide.

Installation

In your terminal, cd into your React project and install the @storyblok/react package.

npm install @storyblok/react

In the root of your project, create a .env file with the access token from your space.

VITE_STORYBLOK_DELIVERY_API_TOKEN="fqc3tdIuC8djNwEYl5cE5Att"

Learn how to retrieve an access token for your Storyblok space.

Initialize the Storyblok client by updating the main.jsx file:

src/main.jsx
import { storyblokInit, apiPlugin } from '@storyblok/react';

storyblokInit({
  accessToken: import.meta.env.VITE_STORYBLOK_ACCESS_TOKEN,
  use: [apiPlugin],
  apiOptions: {
    region: 'eu', // Choose the correct region from your Space.
  },
});

Ensure to set the correct region value depending on the server location of your Storyblok space. Learn more in the @storyblok/js package reference.

The Storyblok package will give you access to features like fetching, components registration and bridge available across your project.

Fetch a single story

In your App.jsx file, call the useStoryblok hook to fetch a story’s data.

src/App.jsx
import { StoryblokComponent, useStoryblok } from '@storyblok/react';

export default function App() {
  const story = useStoryblok('home', {
    version: 'draft'
  });

  if (!story?.content) {
    return <div>Loading...</div>;
  }

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

This page fetches the home story of your Storyblok space using the convenient useStoryblok composable.

The StoryblokComponent dynamically renders content type and nestable blocks. In this case, it looks for the content type block of the home story.

This element detects the content type of the story for you, in this case page and look for a component of the same name to render the story. Learn more in the Storyblok React package reference.

Create and register blocks

Create a storyblok/Page.jsx to render all stories of the page content type.

src/storyblok/Page.jsx
import { StoryblokComponent } from '@storyblok/react';

export default function Page({ blok }) {
  return (
    <main>
      {blok.body?.map((nestedBlok) => (
        <StoryblokComponent blok={nestedBlok} key={nestedBlok._uid} />
      ))}
    </main>
  );
}

Using StoryblokComponent iterate through the body field and render the blocks in it.

Stories might contain a body or similar field which consists of an array with several blocks of custom types (e.g. Feature, Teaser, Grid) in it.

Create the code for these components as follows.

src/storyblok/Feature.jsx
export default function Feature({ blok }) {
  return (
    <div className="feature">
      <span>{blok.name}</span>
    </div>
  );
}
src/storyblok/Teaser.jsx
export default function Teaser({ blok }) {
  return (
    <div className="teaser">
      <h2>{blok.headline}</h2>
    </div>
  );
}
src/storyblok/Grid.jsx
import { StoryblokComponent } from '@storyblok/react';

export default function Grid({ blok }) {
  return (
    <div className="grid">
      {blok.columns.map((nestedBlok) => (
        <StoryblokComponent blok={nestedBlok} key={nestedBlok._uid} />
      ))}
    </div>
  );
}

Similar to Page.jsx, Grid.jsx iterates over the columns block field.

Add all these new components to your app within the main.jsx file.

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

import Page from './storyblok/Page';
import Teaser from './storyblok/Teaser';
import Feature from './storyblok/Feature';
import Grid from './storyblok/Grid';

storyblokInit({
  accessToken: import.meta.env.VITE_STORYBLOK_ACCESS_TOKEN,
  use: [apiPlugin],
  components: {
    page: Page,
    teaser: Teaser,
    feature: Feature,
    grid: Grid,
  },
  apiOptions: {
    region: 'eu',
  },
});

const root = document.getElementById('root');

createRoot(root).render(
  <StrictMode>
    <App/>
  </StrictMode>
);

Run the server and visit the site in your browser.

npm run dev