@storyblok/astro (Version 8.x)
@storyblok/astro is Storyblok’s official development for Astro applications.
Requirements
Section titled “Requirements”- Astro version 3.0 or later
- Node.js LTS (version 22.x recommended)
- Modern web browser (for example, Chrome, Firefox, Safari, Edge — latest versions)
Installation
Section titled “Installation”Add the package to a project by running this command in the terminal:
npm install @storyblok/astro@latestConfiguration
Section titled “Configuration”Import and initialize the SDK using the access token of a Storyblok space.
import { defineConfig } from "astro/config";import { storyblok } from "@storyblok/astro";
export default defineConfig({ integrations: [ storyblok({ accessToken: "YOUR_ACCESS_TOKEN", apiOptions: { region: "eu", }, components: { page: "storyblok/Page", feature: "storyblok/Feature", }, }), ],});Components
Section titled “Components”Create an Astro component for each block defined in Storyblok and registered in the configuration. Each component will receive a blok prop, containing the content of the block.
---import { storyblokEditable } from "@storyblok/astro";const { blok } = Astro.props;---
<div {...storyblokEditable(blok)}> <h2>{blok.headline}</h2></div>Use <StoryblokComponent> to automatically render nested components (provided they are registered globally).
---import { storyblokEditable } from "@storyblok/astro";import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";const { blok } = Astro.props;---
<main {...storyblokEditable(blok)}>{blok.body?.map((blok) => <StoryblokComponent blok={blok} />)}</main>Fetching and rendering
Section titled “Fetching and rendering”In an Astro page or component, use the client to fetch a story and render the content using StoryblokComponent.
---import { useStoryblokApi } from "@storyblok/astro";import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";import BaseLayout from "../layouts/BaseLayout.astro";
const sbApi = useStoryblokApi();const { data } = await sbApi.get("cdn/stories/home", { version: "draft", resolve_relations: ["featured-articles.posts"],});
const story = data.story;---
<BaseLayout> <StoryblokComponent blok={story.content} /></BaseLayout>storyblok
Section titled “storyblok”Import and initialize the SDK to access and configure all features.
import { defineConfig } from "astro/config";import { storyblok } from "@storyblok/astro";export default defineConfig({ integrations: [storyblok(OPTIONS)],});All options listed in the @storyblok/js package reference are available. The following additional options are available:
| Key | Description | Type |
|---|---|---|
bridge | Enable or disable the Storyblok Bridge. Without livePreview being enabled, the Bridge is configured to refresh on saving and publishing the story. Pass an object with Bridge options for additional configuration. See example below. | boolean | object |
components | Register Astro components intended to render Storyblok blocks. Located in the src directory by default. See example below. | object |
componentsDir | Define a custom directory other than src as the location of components. | string |
livePreview | Enable or disable live preview. Disabled by default. | boolean |
enableFallbackComponent | Enable or disable a fallback component to be rendered if no React component has been defined for a Storyblok block. Disabled by default. | boolean |
customFallbackComponent | Register a custom fallback component. Requires enableFallbackComponent to be enabled. See example below. | string |
useCustomApi | By default, the apiPlugin from @storyblok/js is loaded. Disable this behavior by setting useCustomApi to true to optimize the final bundle when using a custom method to fetch data from Storyblok. | boolean |
Example: components
Section titled “Example: components”Register components as follows. The key represents the technical name of the Storyblok block, the value represents the location of the Astro component. The src folder is prepended, the .astro file extension is appended.
storyblok({ components: { page: "storyblok/Page", feature: "storyblok/Feature", grid: "storyblok/Grid", teaser: "storyblok/Teaser", },});Example: customFallbackComponent
Section titled “Example: customFallbackComponent”storyblok({ enableFallbackComponent: true, customFallbackComponent: "storyblok/MyCustomFallback",});Example: bridge
Section titled “Example: bridge”Learn more in the @storyblok/preview-bridge reference. Note that resolveRelations and resolveLinks only become effective when livePreview is enabled.
storyblok({ bridge: { customParent: "iframe-container", preventClicks: true, // Defaults to false. resolveRelations: ["article.author"], resolveLinks: "story", },});useStoryblokApi
Section titled “useStoryblokApi”useStoryblokApi() returns the client instantiated in the application.
---import { useStoryblokApi } from "@storyblok/astro";const storyblokApi = useStoryblokApi();const { data } = await storyblokApi.get(URL, API_OPTIONS);---For the API_OPTIONS, see the storyblok-js-client reference.
storyblokApi
Section titled “storyblokApi”The storyblokApi client provides direct access to the Storyblok API.
import { storyblokApi } from "@storyblok/astro/client";
const { data } = await storyblokApi.get("cdn/stories/home", { version: "draft",});getLiveStory
Section titled “getLiveStory”Deprecated since 8.2.0
getLiveStory returns the updated story object whenever changes are made in the Storyblok Visual Editor, providing a real-time editing experience. Requires livePreview to be enabled.
await getLiveStory(Astro);getPayload
Section titled “getPayload”getPayload provides access to live preview data, including the story and any custom server-side data. Requires livePreview to be enabled.
It enables:
- Access to live preview story data
- Passing and reusing server-side data during preview
- Avoiding unnecessary refetching of external resources
Example: getPayload
Section titled “Example: getPayload”---import { getPayload, useStoryblokApi } from "@storyblok/astro";import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";import StoryblokServerData from "@storyblok/astro/StoryblokServerData.astro";import { getUsers, type User } from "src/lib/getUsers";
interface ServerData { users?: User[];}
interface MyStory extends ISbStoryData { content: { myField: string };}const { slug } = Astro.params;const payload = await getPayload<ServerData, MyStory>({ locals: Astro.locals,});
// Use live preview data or fallback to APIconst story = payload?.story ?? ( await storyblokApi.get(`cdn/stories/${slug || "home"}`, { version: "draft", resolve_relations: ["featured-articles.posts"], }) ).data.story;
const users = payload?.serverData?.users ?? (await getUsers());---
<p>{users?.length} users loaded.</p><StoryblokComponent blok={story.content} /><StoryblokServerData users={users} />StoryblokServerData
Section titled “StoryblokServerData”StoryblokServerData allows for providing pre-fetched server-side data to the live preview environment.
This is useful when an application depends on external data sources (for example, APIs, databases) that are slow or expensive to fetch repeatedly. The data is sent once and reused during live preview updates.
<StoryblokServerData users={users} />StoryblokComponent
Section titled “StoryblokComponent”This component automatically renders Storyblok blocks for corresponding Astro components registered using the components option of the storyblok Astro integration. It requires a blok property. Any additional passed properties are forwarded to the Astro component.
<StoryblokComponent blok={story.content} />Use it to iterate over blocks fields as follows:
{ blok.nested_bloks?.map((currentBlok) => <StoryblokComponent blok={currentBlok} />);}storyblokEditable
Section titled “storyblokEditable”This function connects Astro components to their Storyblok counterparts, adding HTML attributes that allow the Storyblok Bridge to work. See the @storyblok/js reference for further details.
---import { storyblokEditable } from "@storyblok/astro";
const { blok } = Astro.props;---
<section {...storyblokEditable(blok)}>{blok.title}</section>renderRichText
Section titled “renderRichText”This function converts a Storyblok rich text field into HTML.
---import { renderRichText } from "@storyblok/astro";
const { blok } = Astro.props;const renderedRichText = renderRichText(blok.richtext_field);---
<div set:html={renderedRichText} />See the @storyblok/richtext reference for further details.
Live preview
Section titled “Live preview”Events
Section titled “Events”Use these events to hook into the live preview rendering lifecycle:
storyblok-live-preview-updating: Triggered when a live preview update starts (before the DOM is updated).storyblok-live-preview-updated: Triggered after the DOM has been updated.
<script> document.addEventListener("storyblok-live-preview-updating", () => { console.log("Storyblok live preview: DOM updating"); });
document.addEventListener("storyblok-live-preview-updated", () => { console.log("Storyblok live preview: DOM updated"); });</script>Preserve component state
Section titled “Preserve component state”Use the data-preserve-state attribute to prevent parts of the UI from re-rendering during live preview updates.
<div data-preserve-state></div>Disable live preview per route
Section titled “Disable live preview per route”Use the storyblok-live-preview meta tag to disable live preview for specific routes.
<meta name="storyblok-live-preview" content="disabled" />Editor-controlled updates
Section titled “Editor-controlled updates”Use the storyblok-live-preview-updating event to listen to live preview update events and control rendering behavior:
document.addEventListener("storyblok-live-preview-updating", (event) => { event.preventDefault();});Further resources
Section titled “Further resources”Previous versions
Section titled “Previous versions”Was this page helpful?
This site uses reCAPTCHA and Google's Privacy Policy (opens in a new window) . Terms of Service (opens in a new window) apply.
Get in touch with the Storyblok community