Skip to content

@storyblok/react is Storyblok’s official SDK for React applications.

  • React version 17 or later
  • Node.js LTS (version 22.x recommended)
  • Modern web browser (e.g., Chrome, Firefox, Safari, Edge – latest versions)

Add the package to a project by running this command in the terminal:

Terminal window
npm install @storyblok/react@latest
ExportWhen to useHow to use
@storyblok/reactClient-rendered apps and SPAs.Use useStoryblok and StoryblokComponent.
@storyblok/react/ssrPrerendering, and static export (including Next.js output: 'export'). Live editing is not supported.Use StoryblokServerStory for rendering components. The bridge is not loaded.
@storyblok/react/rscNext.js App Router and other RSC setups.Use StoryblokStory in server components so the bridge and live editing work in the visual editor. Use StoryblokServerComponent for nested blocks and StoryblokComponent in client components.

Import and initialize the SDK using the access token of a Storyblok space.

src/main.jsx
import { apiPlugin, storyblokInit } from "@storyblok/react";
import Page from "./Page.js";
import Feature from "./Feature.js";
storyblokInit({
accessToken: "YOUR_ACCESS_TOKEN",
use: [apiPlugin],
apiOptions: {
region: "eu",
},
components: {
page: Page,
feature: Feature,
},
});

Create a React component for each block defined in Storyblok and registered in the configuration. Each component will receive a blok prop, containing the content of the block.

const Feature = ({ blok }) => (
<div>
<h2>{blok.headline.text}</h2>
</div>
);
export default Feature;

Use <StoryblokComponent> to automatically render nested components (provided they are registered globally).

src/storyblok/Page.jsx
import { StoryblokComponent } from "@storyblok/react";
export default function Page({ blok }) {
return <section>{blok.body ? blok.body.map((blok) => <StoryblokComponent blok={blok} key={blok._uid} />) : null}</section>;
}

Use the client to fetch a story and render the content using StoryblokComponent.

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} />;
}

Import and initialize the SDK to access and configure all features.

import { storyblokInit } from "@storyblok/react";
storyblokInit(OPTIONS);

storyblokInit() creates an instance of the Storyblok API client and loads the Storyblok Bridge.

All options listed in the @storyblok/js package reference are available. The following additional options are available:

KeyDescriptionType
componentsAn object that maps React components to Storyblok blocks. Each component receives a blok prop containing the content of the block.object
enableFallbackComponentEnable or disable a fallback component to be rendered if no React component has been defined for a Storyblok block. Disabled by default.boolean
customFallbackComponentRegister a custom fallback component. Requires enableFallbackComponent to be enabled.React component

apiPlugin configures the implementation of the Storyblok API. It is imported from @storyblok/js.

import { storyblokInit, apiPlugin } from "@storyblok/react";
storyblokInit({ use: [apiPlugin] });

See the @storyblok/js reference for further details.

Enable both data fetching and bridge capabilities using this function.

import { useStoryblok } from "@storyblok/react";
export default function App() {
const story = useStoryblok(URL, API_OPTIONS, BRIDGE_OPTIONS);
}

For the API_OPTIONS, see the storyblok-js-client reference. For the BRIDGE_OPTIONS, see the @storyblok/preview-bridge reference.

useStoryblokApi() returns the client instantiated in the application.

import { useStoryblokApi } from "@storyblok/react";
import { useEffect, useState } from "react";
export default function App() {
const storyblokApi = useStoryblokApi();
const [data, setData] = useState(null);
useEffect(() => {
async function fetchData() {
const response = await storyblokApi.get(URL, API_OPTIONS);
setData(response.data);
}
fetchData();
}, []);
}

For the API_OPTIONS, see the storyblok-js-client reference.

getStoryblokApi() is an alias of useStoryblokApi().

useStoryblokBridge() activates the Storyblok Bridge.

import { useStoryblokApi, useStoryblokBridge } from "@storyblok/react";
import { useEffect, useState } from "react";
export default function App() {
const storyblokApi = useStoryblokApi();
const [data, setData] = useState(null);
useEffect(() => {
async function fetchData() {
const response = await storyblokApi.get(URL, API_OPTIONS);
setData(response.data);
}
fetchData();
}, []);
useStoryblokBridge(STORY_ID, CALLBACK, BRIDGE_OPTIONS);
}

For the BRIDGE_OPTIONS, see the @storyblok/preview-bridge reference.

It is possible to access the Storyblok Bridge via window instead of using useStoryblokBridge as shown below:

const storyblokBridge = new window.StoryblokBridge(options);
storyblokBridge.on(["input", "published", "change"], (event) => {
// ...
});

registerStoryblokBridge() is an alias of useStoryblokBridge().

Activates the Storyblok Bridge on the window.

loadStoryblokBridge();

useStoryblokState() accepts a story from the Storyblok API and makes it reactive for live editing.

import { useStoryblokState } from "@storyblok/react";
export default function Home({ story: STORY_OBJECT }) {
const story = useStoryblokState(STORY_OBJECT);
if (!story.content) {
return <div>Loading...</div>;
}
}

StoryblokStory maintains the state of a story and uses StoryblokComponent to render the route components dynamically, using the list of components loaded via storyblokInit. Use StoryblokComponent inside components to render nested components dynamically.

StoryblokStory accepts a story from the Storyblok API and bridge options.

<StoryblokStory story={STORY_OBJECT} bridgeOptions={BRIDGE_OPTIONS} />

For the BRIDGE_OPTIONS, see the @storyblok/preview-bridge reference.

StoryblokComponent is a React component that dynamically renders blocks from Storyblok.

StoryblokComponent accepts a blok prop, which should be a block from the Storyblok API. Any other props passed to StoryblokComponent will be passed directly to the block component.

<StoryblokComponent blok={blok} />

Use it to iterate over blocks fields as follows:

{
blok.nested_bloks?.map((currentBlok, index) => <StoryblokComponent blok={currentBlok} key={currentBlok._uid || index} />);
}

Use StoryblokServerComponent rather than StoryblokComponent when using React Server Components.

storyblokEditable() accepts a block from the Storyblok API and returns an object containing the HTML attributes to make elements editable in the Storyblok Visual Editor. See the @storyblok/js reference for further details.

const Feature = ({ blok }) => {
return (
<section {...storyblokEditable(blok)} key={blok._uid}>
{blok.title}
</section>
);
};

setComponents() updates the component map of the current client instance.

setComponents(COMPONENTS_OBJECT);

Used to render a rich text field from a Storyblok story.

<StoryblokRichText document={blok.richtext_field} />

The component accepts the following optional props:

  • components: Allows custom React components to be provided for supported rich text nodes and marks.
  • optimizeImage: Allows image optimization options to be configured for image nodes.

See the @storyblok/richtext reference for a complete list of supported nodes, marks, and customization options.

Custom components can be registered using the components prop. The key must match a supported rich text node or mark name.

import type { SbReactRichTextComponentMap } from "@storyblok/react";
const components: SbReactRichTextComponentMap = {
heading: CustomHeading,
link: CustomLink,
table: CustomTable,
bold: ({ children }) => <b className="font-bold text-black">{children}</b>,
};

The components can then be passed to StoryblokRichText:

<StoryblokRichText document={blok.richtext_field} components={components} />

Marks receive their rendered child content through the children prop.

import type { SbReactRichTextProps } from "@storyblok/react";
import Link from "next/link";
export function CustomLink({ children, attrs }: SbReactRichTextProps<"link">) {
return (
<Link href={attrs?.href ?? ""} target={attrs?.target ?? "_self"}>
{children}
</Link>
);
}

Nodes can use the children prop to render child content.

import type { SbReactRichTextProps } from "@storyblok/react";
export function CustomHeading({ children, attrs }: SbReactRichTextProps<"heading">) {
const Tag = `h${attrs?.level ?? 1}` as keyof JSX.IntrinsicElements;
return <Tag className="custom-heading">{children}</Tag>;
}

Example: Custom table component (advanced node)

Section titled “Example: Custom table component (advanced node)”

For advanced use cases, nodes can access content and context to recursively render child nodes using StoryblokRichText.

The splitTableRows utility can be used to separate table header rows from body rows when creating custom table components.

import { StoryblokRichText, splitTableRows, type SbReactRichTextProps } from "@storyblok/react";
export function CustomTable({ content, context }: SbReactRichTextProps<"table">) {
const { headerRows, bodyRows } = splitTableRows(content);
return (
<table className="custom-table">
{headerRows && (
<thead>
<StoryblokRichText document={headerRows} {...context} />
</thead>
)}
<tbody>
<StoryblokRichText document={bodyRows} {...context} />
</tbody>
</table>
);
}

StoryblokServerRichText should be used instead of StoryblokRichText when working with React Server Components.

It provides the same API as StoryblokRichText, including support for the components and optimizeImage props.

useStoryblokRichText can be used to programmatically render rich text content.

import { useStoryblokRichText, type SbReactRichTextComponentMap } from "@storyblok/react";
import CustomLink from "./CustomLink";
const components: SbReactRichTextComponentMap = {
link: CustomLink,
};
function App() {
const render = useStoryblokRichText({ components });
const richText = render(blok.articleContent);
return richText;
}

It accepts the same configuration options as StoryblokRichText, including components and optimizeImage.

The React SDK also exports the core rich text utilities from @storyblok/richtext. These can be useful when implementing advanced custom components, such as custom image or table rendering.

Available utilities include:

  • renderRichText: The core rich text rendering function.
  • buildStoryblokImage: Generates optimized Storyblok Image Service URLs.
  • splitTableRows: Splits table rows into headerRows and bodyRows.

Was this page helpful?

What went wrong?

This site uses reCAPTCHA and Google's Privacy Policy (opens in a new window) . Terms of Service (opens in a new window) apply.