---
title: Integrate Next.js with Storyblok
description: This guide walks you through integrating Storyblok as a headless CMS, fetching content, and building components to render it effectively in your Next.js project.
url: https://storyblok.com/docs/guides/nextjs
---

# Integrate Next.js with Storyblok

Use Storyblok to manage the content of your website built with the Next.js app router.

> [!NOTE]
> This guide has been tested with the following package versions:
> 
> -   `next@16.2.1`
> -   `react@19.2.4`
> -   `react-dom@19.2.4`
> -   `@storyblok/react@6.1.0`
> -   Node.js v24.7.0

## Setup

Create a new Next.js project by following the [Installation](https://nextjs.org/docs/app/getting-started/installation) page from its official documentation.

> [!WARNING]
> Choose the app router option and answer **yes** when asked to organize the code inside a `src` directory.

If you already have a Storyblok account, go to [app.storyblok.com](http://app.storyblok.com/#/signup) or [log in with GitHub](https://github.com/login?client_id=Iv23liC8pLXD6VcT2EbS&return_to=%2Flogin%2Foauth%2Fauthorize%3Fclient_id%3DIv23liC8pLXD6VcT2EbS%26redirect_uri%3Dhttps%253A%252F%252Fapp.storyblok.com%252F#/login) to continue.

Create a [new blank space](https://app.storyblok.com/#/me/spaces/new?tab=select-plan) to follow the tutorial from scratch, or start from the [core blueprint](https://app.storyblok.com/#/spaces/new/blueprint?blueprintReference=starter).

[Create one and start a free Storyblok space](https://app.storyblok.com/#/signup) No Storyblok account yet?

## Installation

In the terminal, `cd` into the Next.js project and install the `@storyblok/react` package.

```bash
npm install @storyblok/react@latest
```

Create a new file under `src/lib/storyblok.js` and initialize the Storyblok module:

src/lib/storyblok.js

```javascript
import { apiPlugin, storyblokInit } from '@storyblok/react/rsc';

export const getStoryblokApi = storyblokInit({
  accessToken: process.env.STORYBLOK_DELIVERY_API_TOKEN,
  use: [apiPlugin],
  apiOptions: {
    region: 'eu',
  },
});
```

> [!WARNING]
> Ensure to set the correct `region` value depending on the server location of your Storyblok space. Learn more in the [@storyblok/js package reference](https://www.storyblok.com/docs/libraries/js/js-sdk).

In the root of your project, create a `.env` file with the access token from your space. Since this token is not prefixed with `NEXT_PUBLIC`, it will not be available for client-side rendering. Learn more about tokens in Next.js in their [documentation](https://nextjs.org/docs/pages/guides/environment-variables).

.env

```bash
STORYBLOK_DELIVERY_API_TOKEN=<YOUR-ACCESS-TOKEN>
```

> [!NOTE]
> Learn how to get an [access token](/docs/concepts/access-tokens) for your Storyblok project.

Add a `src/components/StoryblokProvider.jsx` file with the following content:

src/components/StoryblokProvider.jsx

```javascript
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.

src/app/layout.js

```javascript
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

> [!NOTE]
> Using the correct export
> 
> The `@storyblok/react` SDK has different exports for various rendering modes. For this Next.js guide, we are building a server-side rendered application, so we will use the import from `@storyblok/react/rsc`. Learn more about the library's rendering modes in the [documentation](/docs/libraries/js/react-sdk).

  

Replace the code in `src/app/page.js` with the following.

src/app/page.js

```javascript
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

Create a `src/components/Page.jsx` component to render all stories of the `page` content type, such as the home story.

src/components/Page.jsx

```javascript
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.

src/components/Feature.jsx

```javascript
export default function Feature({ blok }) {
  return (
    <div className="feature">
      <span>{blok.name}</span>
    </div>
  );
}
```

src/components/Teaser.jsx

```javascript
export default function Teaser({ blok }) {
  return (
    <div className="teaser">
      <h2>{blok.headline}</h2>
    </div>
  );
}
```

src/components/Grid.jsx

```javascript
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.

src/lib/storyblok.js

```javascript
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_TOKEN,
  use: [apiPlugin],
  components: {
    page: Page,
    feature: Feature,
    grid: Grid,
    teaser: Teaser
  },
  apiOptions: {
    region: 'eu',
  },
});
```

Run the server and visit the site in your browser.

```bash
npm run dev
```

## Related resources

[Storyblok's Next.js Blueprint Repository](https://github.com/storyblok/blueprint-core-nextjs)

[@storyblok/react Package Reference](https://www.storyblok.com/docs/libraries/js/react-sdk)

[Concept: Blocks](/docs/concepts/blocks)

[Content Delivery API: Retrieve a Single Story](/docs/api/content-delivery/v2/stories/retrieve-a-single-story)

[Next.js Docs](https://nextjs.org/docs)

  

## Pagination

-   [Next: Visual Preview in Next.js](/docs/guides/nextjs/visual-preview)
