Integrate Next.js with Storyblok
Use Storyblok to manage the content of your website built with the Next.js app router.
Create a new Next.js project by following the Installation page from its official documentation.
If you already have a Storyblok account, go to app.storyblok.com or log in with GitHub to continue.
Create a new blank space (opens in a new window) to follow the tutorial from scratch, or start from the core blueprint (opens in a new window).
Installation
Section titled “Installation”In the terminal, cd into the Next.js project and install the @storyblok/react package.
npm install @storyblok/react@latestCreate a new file under src/lib/storyblok.js and initialize the Storyblok module:
import { apiPlugin, storyblokInit } from '@storyblok/react/rsc';
export const getStoryblokApi = storyblokInit({ accessToken: process.env.NEXT_PUBLIC_STORYBLOK_CONTENT_API_ACCESS_TOKEN, use: [apiPlugin], apiOptions: { region: 'eu', },});In the root of your project, create a .env file with the access token from your space.
NEXT_PUBLIC_STORYBLOK_CONTENT_API_ACCESS_TOKEN=<YOUR-ACCESS-TOKEN>Add a src/components/StoryblokProvider.jsx file with the following content:
"use client";
import { getStoryblokApi } from "@/lib/storyblok";
export default function StoryblokProvider({ children }) { getStoryblokApi(); return children;}In the existing src/app/layout.js file, import the StoryblokProvider component and wrap the RootLayout one.
import StoryblokProvider from "@/components/StoryblokProvider";
export default function RootLayout({ children }) { return ( <StoryblokProvider> <html lang="en"> <body> {children} </body> </html> </StoryblokProvider> );}The StoryblokProvider component will make features like fetching, component registration, and bridge available across your project.
Fetch a single story
Section titled “Fetch a single story”Replace the code in src/app/page.js with the following.
import { getStoryblokApi } from '@/lib/storyblok';import { StoryblokStory } from '@storyblok/react/rsc';
export default async function Home() { const { data } = await fetchData();
return ( <div className="page"> <StoryblokStory story={data.story} /> </div> );}
export async function fetchData() { const storyblokApi = getStoryblokApi(); return await storyblokApi.get(`cdn/stories/home`, { version: 'draft' });}The StoryblokStory dynamically renders content type and nestable blocks. In this case, it looks for the content type block of the home story.
Create and register blocks
Section titled “Create and register blocks”Create a src/components/Page.jsx component to render all stories of the page content type, such as the home story.
import { storyblokEditable, StoryblokServerComponent,} from '@storyblok/react/rsc';
export default function Page({ blok }) { return ( <main> {blok.body?.map((nestedBlok) => ( <StoryblokServerComponent blok={nestedBlok} key={nestedBlok._uid} /> ))} </main> );}Using StoryblokServerComponent iterate through the body field and render the blocks in it.
Stories might contain a body or a similar blocks 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.
export default function Feature({ blok }) { return ( <div className="feature"> <span>{blok.name}</span> </div> );}export default function Teaser({ blok }) { return ( <div className="teaser"> <h2>{blok.headline}</h2> </div> );}import { StoryblokServerComponent } from '@storyblok/react/rsc'
export default function Grid({ blok }){ return ( <div className="grid"> {blok.columns?.map((nestedBlok) => ( <StoryblokServerComponent blok={nestedBlok} key={nestedBlok._uid} /> ))} </div> );};Similar to Page.jsx, Grid.jsx iterates over the columns block field.
Add these components to the src/lib/storyblok.js file.
import Page from "@/components/Page";import Feature from "@/components/Feature";import Grid from "@/components/Grid";import Teaser from "@/components/Teaser";
import { apiPlugin, storyblokInit } from "@storyblok/react/rsc";
export const getStoryblokApi = storyblokInit({ accessToken: process.env.STORYBLOK_DELIVERY_API_ACCESS_TOKEN use: [apiPlugin], components: { page: Page, feature: Feature, grid: Grid, teaser: Teaser }, apiOptions: { endpoint: "https://api.storyblok.com", },});Run the server and visit the site in your browser.
npm run devRelated resources
Section titled “Related resources”Get in touch with the Storyblok community