---
title: Integrate Next.js with Storyblok
description: This guide explains how to integrate Storyblok as a headless CMS, fetch content, and render components in a Next.js project.
url: https://www.storyblok.com/docs/quickstarts/nextjs
---

# Integrate Next.js with Storyblok

Use Storyblok to manage the content of your Next.js project. Follow this guide to learn how to fetch content, register components, set up previews, configure a catch-all route, and build a content model.

## Quickstart

The fastest way to get started is using Storyblok’s Core Blueprint or CLI wizard:

-   Blueprint (UI)
    
    Use [Storyblok’s Core Blueprint](/docs/concepts/blueprints) to [launch a Next.js project](https://app.storyblok.com/#/spaces/new/blueprint?blueprintReference=starter), complete with a space, GitHub repository, and deployment environment.
    
    Log in to [Storyblok](https://app.storyblok.com/#/me/spaces), select **\+ Add Space** → **Start from Blueprint**, and follow the steps.
    
-   CLI
    
    Use [Storyblok’s CLI](/docs/tooling/cli) to set up a new space and scaffold a Next.js project. In the terminal, run:
    
    ```bash
    storyblok create --template nextjs
    ```

## Manual setup

Alternatively, set up the project from scratch and configure your frontend code.

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`

[No Storyblok account?](https://app.storyblok.com/#/signup)Sign up and create a space for free

1.  **Create a [new space](https://app.storyblok.com/#/me/spaces/new?tab=select-plan)**
    
    Log in to [Storyblok](https://app.storyblok.com/#/me/spaces), select **\+ Add Space** → **New Space**, and follow the steps.
    
2.  **Create a Next.js project**
    
    Create a new Next.js project following the official [installation guide](https://nextjs.org/docs/app/getting-started/installation).
    
3.  **Install `@storyblok/react`**
    
    In the terminal, `cd` into the project, and install the package.
    
    ```bash
    npm install @storyblok/react
    ```
    

Next, in the root of your project, create a `.env` file with the [access token](/docs/concepts/access-tokens) from your space:

.env

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

> [!NOTE]
> To make the token available for client-side rendering, prefix it with `NEXT_PUBLIC_`. Learn more in the [official documentation](https://nextjs.org/docs/pages/guides/environment-variables).

In `src/lib/`, create a `storyblok.js` file 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",
  },
});
```

> [!NOTE]
> Use the `region` key that matches your space’s server location. Learn more in the [JavaScript SDK reference](/docs/libraries/js/js-sdk#the-region-parameter).

In `src/components/`, create a `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`:

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 makes 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 can have a `body` field that contains an array of custom type blocks, such as Feature, Teaser, and Grid.

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

-   [Previous: Internationalization in Astro](/docs/quickstarts/astro/internationalization)
-   [Next: Visual Preview in Next.js](/docs/quickstarts/nextjs/visual-preview)
