Storyblok
Search Storyblok's Documentation
  1. Integrate Astro with Storyblok

Integrate Astro with Storyblok

Use Storyblok to manage the content of your Astro website.

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

If you don’t already have a Storyblok space, create a starter space at app.storyblok.com, it already comes with initial content and component used in the first part of this guide.

Installation

In the terminal, cd into the Astro project and install the @storyblok/astro package.

npm install @storyblok/astro@latest

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

astro.config.mjs
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',
});

Ensure to set the correct region value depending on the server location of your Storyblok space. Learn more in the @storyblok/js package reference.

In the root of the project, create a .env file to store the Storyblok access token.

.env
STORYBLOK_DELIVERY_API_TOKEN=<YOUR-ACCESS-TOKEN>

Learn how to get an access token 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
---
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
---
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 (e.g. Feature, Teaser, Grid) in it.

Create the code for these components as follows.

src/storyblok/Feature.astro
---
const { blok } = Astro.props
---

<div class="feature">
  <span>{blok.name}<span>
</div>
src/storyblok/Teaser.astro
---
const { blok } = Astro.props;
---

<section class="teaser">
  <h2>{blok.headline}</h2>
</section>
src/storyblok/Grid.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
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.

npm run dev