How to Use Storyblok with Astro: Complete Guide
Step-by-step guide to integrating Storyblok with your Astro website.
Storyblok is a visual headless CMS that lets content editors work with a real-time preview of the page they are building. Unlike most headless CMS platforms where editors work in a form and hope the output looks right, Storyblok shows them exactly what the page will look like. For teams with non-technical editors, this is a significant advantage.
Astro has an official Storyblok integration, which makes the setup straightforward. You get the visual editor, component-based content, and Astro's static performance in one package.
Prerequisites
- Node.js 18+
- An Astro project (
npm create astro@latest) - A Storyblok account (free tier available with 1 space)
Installation
Install the official Astro Storyblok integration:
npx astro add @storyblok/astro
This command installs the package and updates your astro.config.mjs automatically. If you prefer manual installation:
npm install @storyblok/astro
Configuration
Get your access token from Storyblok under Settings > Access Tokens. Use the "Preview" token for development and the "Public" token for production.
Update your astro.config.mjs:
// astro.config.mjs
import { defineConfig } from "astro/config";
import storyblok from "@storyblok/astro";
export default defineConfig({
integrations: [
storyblok({
accessToken: import.meta.env.STORYBLOK_TOKEN,
components: {
page: "storyblok/Page",
blogPost: "storyblok/BlogPost",
hero: "storyblok/Hero",
richtext: "storyblok/RichText",
},
apiOptions: {
region: "eu", // or "us" depending on your space
},
}),
],
});
Add your token to .env:
STORYBLOK_TOKEN=your_preview_or_public_token
Basic Usage
Create Astro components that map to your Storyblok content types. Storyblok uses a "blok" system where each content block maps to a component.
---
// src/storyblok/BlogPost.astro
import { storyblokEditable, renderRichText } from "@storyblok/astro";
const { blok } = Astro.props;
const renderedContent = renderRichText(blok.content);
---
<article {...storyblokEditable(blok)}>
<h1>{blok.title}</h1>
{blok.image?.filename && (
<img
src={`${blok.image.filename}/m/800x450`}
alt={blok.image.alt}
loading="lazy"
/>
)}
<div set:html={renderedContent} />
</article>
Now create a dynamic page that fetches content from Storyblok:
---
// src/pages/blog/[...slug].astro
import { useStoryblokApi } from "@storyblok/astro";
import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";
import BaseLayout from "../../layouts/BaseLayout.astro";
export async function getStaticPaths() {
const storyblokApi = useStoryblokApi();
const { data } = await storyblokApi.get("cdn/stories", {
content_type: "blogPost",
version: import.meta.env.DEV ? "draft" : "published",
});
return data.stories.map((story: any) => ({
params: { slug: story.slug },
props: { story },
}));
}
const { story } = Astro.props;
---
<BaseLayout title={story.name}>
<StoryblokComponent blok={story.content} />
</BaseLayout>
Production Tips
Use Storyblok's image service. Append
/m/followed by dimensions to any image URL for on-the-fly resizing. For example,image.filename + "/m/600x400/filters:format(webp)"gives you a resized WebP image without any extra tooling.
Set up the Visual Editor correctly. In Storyblok's settings, configure the preview URL to point to your local dev server (https://localhost:4321). The storyblokEditable helper adds the data attributes needed for the editor to highlight components.
Use the "resolve_relations" parameter. When content references other stories (like author profiles or related posts), pass resolve_relations: "blogPost.author" in your API call to get the full data in one request.
Configure webhooks for rebuilds. Under Settings > Webhooks, set up a trigger that fires when stories are published. Point it at your hosting platform's deploy hook.
Separate draft and published content. Use version: "draft" during development and version: "published" in production. This lets editors preview changes without affecting the live site.
Alternatives to Consider
- Sanity if you prefer schema-as-code and real-time collaboration without a visual page builder.
- DatoCMS if you want a simpler form-based CMS with excellent image optimization built in.
- Contentful if you need a larger integration ecosystem and enterprise features like content approval workflows.
Wrapping Up
Storyblok and Astro work well together, especially when your content team needs visual editing capabilities. The official integration handles most of the boilerplate, the component mapping system keeps your code organized, and the image service means you do not need a separate media pipeline. If your editors want to see their changes in real time before publishing, this is the CMS to pick.
Related Articles
How to Use Algolia with Astro: Complete Guide
Step-by-step guide to integrating Algolia with your Astro website.
How to Integrate Auth0 with Astro: Complete Guide
Step-by-step guide to integrating Auth0 with your Astro website. Setup, configuration, and best practices.
How to Use AWS Amplify with Astro: Complete Guide
Step-by-step guide to integrating AWS Amplify with your Astro website.