---
title: Integrate Astro 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 Astro project.
url: https://storyblok.com/docs/guides/astro
---

# Integrate Astro with Storyblok

Use Storyblok to manage the content of your Astro website.

> [!NOTE]
> This guide has been tested with the following package versions:
> 
> -   `astro@5.7.14`
> -   `storyblok-astro@6.2.0`
> -   Node.js v22.13.0

## Setup

Create a new Astro project following the [official installation](https://docs.astro.build/en/install-and-setup/) page.

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 Astro project and install the `@storyblok/astro` package.

```bash
npm install @storyblok/astro
```

In the `astro.config.mjs` file, initialize the Storyblok module:

astro.config.mjs

```javascript
import { defineConfig } from 'astro/config';
import { storyblok } from '@storyblok/astro';
import { loadEnv } from 'vite';
const env = loadEnv('', process.cwd(), 'STORYBLOK');
const { STORYBLOK_DELIVERY_API_TOKEN } = loadEnv(
  import.meta.env.MODE,
  process.cwd(),
  '',
);

export default defineConfig({
  integrations: [
    storyblok({
      accessToken: env.STORYBLOK_DELIVERY_API_TOKEN,
      apiOptions: {
        region: 'eu',
      },
    }),
  ],
  output: 'server',
});
```

> [!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 the project, create a `.env` file to store the Storyblok access token.

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

The Storyblok integration will make features like fetching, components registration and bridge available across your project.

## Fetch a single story

In the `src/pages/index.astro` file, replace Astro's default contents with the following.

src/pages/index.astro

```astro
---
import { useStoryblokApi } from "@storyblok/astro";
import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";
import Layout from "../layouts/Layout.astro";

const storyblokApi = useStoryblokApi()
const { data } = await storyblokApi.get("cdn/stories/home", {
  version: "draft",
});

const { story } = data;
---

<Layout>
  <StoryblokComponent blok={story.content} />
</Layout>
```

The `StoryblokComponent` 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 `Page.astro` component to render all stories of the `page` content type, such as the home story.

src/storyblok/Page.astro

```astro
---
import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";
const { blok } = Astro.props;
---

<main>
  {
    blok.body?.map((blok) => {
      return <StoryblokComponent blok={blok} />;
    })
  }
</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 (for example, Feature, Teaser, Grid) in it.

Create the code for these components as follows.

src/storyblok/Feature.astro

```astro
---
const { blok } = Astro.props
---

<div class="feature">
  <span>{blok.name}<span>
</div>
```

src/storyblok/Teaser.astro

```astro
---
const { blok } = Astro.props;
---

<div class="teaser">
  <h2>{blok.headline}</h2>
</div>
```

src/storyblok/Grid.astro

```astro
---
import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";
const { blok } = Astro.props;
---

<div class="grid">
  {
    blok.columns?.map((nestedBlok) => {
      return <StoryblokComponent blok={nestedBlok} />
    })
  }
</div>
```

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

Add these components to the `astro.config.mjs` file.

astro.config.mjs

```javascript
import { defineConfig } from "astro/config";
import { storyblok } from "@storyblok/astro";
import { loadEnv } from "vite";
const env = loadEnv("", process.cwd(), "STORYBLOK");const { STORYBLOK_DELIVERY_API_TOKEN} = loadEnv(import.meta.env.MODE, process.cwd(), "");

export default defineConfig({
  integrations: [
    storyblok({
      accessToken: env.STORYBLOK_DELIVERY_API_TOKEN,
      apiOptions: {
        region: "eu", // Optional. Defaults to "eu"
      },
      components: {
      page: "storyblok/Page",
      grid: "storyblok/Grid",
      feature: "storyblok/Feature",
      teaser: "storyblok/Teaser",
    }
    }),
  ],
  output: 'server',
});
```

Run the server and visit the site in your browser.

```bash
npm run dev
```

## Related resources

[Storyblok's Astro Blueprint Repository](https://github.com/storyblok/blueprint-core-astro)

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

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

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

[Astro Docs](https://astro.build/docs)

  

## Pagination

-   [Next: Visual Preview in Astro](/docs/guides/astro/visual-preview)
