@storyblok/astro
Astro module for the Storyblok Headless CMS.
Live Demo
If you are in a hurry, check out our official live demo on StackBlitz.
🚀 Usage
If you are first-time user of Storyblok, read the Getting Started guide to get a project ready in less than 5 minutes.
Installation
Install @storyblok/astro
:
npm install @storyblok/astro
Add the following code to astro.config.mjs
and replace the accessToken
with the preview API token of your Storyblok space.
import { defineConfig } from "astro/config";
import storyblok from "@storyblok/astro";
export default defineConfig({
integrations: [
storyblok({
accessToken: "<your-access-token>",
}),
],
});
Options
When you initialize the module, you can pass all @storyblok/js options
storyblok({
accessToken: "<your-access-token>",
bridge: true,
apiOptions: {},
use: [apiPlugin],
});
Note: if you don't use apiPlugin
, you can use your preferred method or function to fetch your data.
Getting started
1. Creating and linking your components to the Storyblok Visual Editor
In order to link your Astro components to their equivalents you created in Storyblok:
First, you need to load them globally by specifying their name and their path in astro.config.mjs
:
components: {
page: "storyblok/Page",
feature: "storyblok/Feature",
grid: "storyblok/Grid",
teaser: "storyblok/Teaser",
},
Note: The src
folder is automatically added to the beginning of the path, so in this example your Astro components should be located here:
src/storyblok/Page.astro
src/storyblok/Feature.astro
src/storyblok/Grid.astro
src/storyblok/Teaser.astro
You can choose any other folder in the src
directory for your Astro components.
For each component, use the storyblokEditable()
function on its root element, passing the blok
property that they receive:
---
import { storyblokEditable } from '@storyblok/astro';
const { blok } = Astro.props
---
<div {...storyblokEditable(blok)}>
<h2>{blok.headline}</h2>
</div>
Finally, you can use the provided <StoryblokComponent>
for nested components; it will automatically render them (if they have been registered globally beforehand):
---
import { storyblokEditable } from '@storyblok/astro';
import StoryblokComponent from '@storyblok/astro/StoryblokComponent.astro';
const { blok } = Astro.props
---
<main {...storyblokEditable(blok)}>
{blok.body?.map(blok => {return <StoryblokComponent blok={blok} />})}
</main>
Note: The blok
is the actual blok data coming from Storblok's Content Delivery API.
Using partial hydration
If you want to use partial hydration with any of the frameworks supported by Astro, follow these steps:
- Install the official Astro integration for your desired framework
- Create an Astro component that serves as a wrapper and utilizes the most suitable client directive
- Create the actual component in Vue, Svelte, React or any other supported framework
For working examples, please refer to the Live Demo on Stackblitz.
2. Getting Storyblok Stories and using the Storyblok Bridge
Fetching one Story
Use the useStoryblokApi
function to have access to an instance of storyblok-js-client
:
---
import { useStoryblokApi } from "@storyblok/astro";
import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";
const storyblokApi = useStoryblokApi();
const { data } = await storyblokApi.get("cdn/stories/home", {
version: "draft",
});
const story = data.story;
---
<StoryblokComponent blok={story.content} />
Note: The available methods are described in the [storyblok-js-client] repository(https://github.com/storyblok/storyblok-js-client#method-storyblokget)
Dynamic Routing
In order to dynamically generate Astro pages based on the Stories in your Storyblok Space, you can use the Storyblok Links API and the Astro getStaticPaths()
function similar to this example:
---
import { useStoryblokApi } from "@storyblok/astro";
import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";
export async function getStaticPaths() {
const storyblokApi = useStoryblokApi();
const { data } = await storyblokApi.get("cdn/links", {
version: "draft",
});
let links = data.links;
links = Object.values(links);
return links.map((link) => {
return {
params: { slug: link.slug },
};
});
}
const { slug } = Astro.params;
const storyblokApi = useStoryblokApi();
const { data } = await storyblokApi.get(`cdn/stories/${slug}`, {
version: "draft",
});
const story = data.story;
---
<StoryblokComponent blok={story.content} />
Using the Storyblok Bridge
The Storyblok Bridge is automatically activated by default. If you would like to disable it or enable it conditionally (e.g. depending on the environment) you can set the bridge
parameter to false
in astro.config.mjs
:
Note: Since Astro is not a reactive JavaScript framework and renders everything as HTML, the Storyblok Bridge will not provide real-time editing as you may know it from other frameworks. However, it automatically refreshes the site for you whenever you save or publish a story.
Rendering Rich Text
You can easily render rich text by using the renderRichText
function that comes with @storyblok/astro
. Then you can use the set:html
directive:
---
import { renderRichText } from '@storyblok/astro';
const { blok } = Astro.props
const renderedRichText = renderRichText(blok.text)
---
<div set:html={renderedRichText}></div>
API
useStoryblokApi()
Returns the instance of the storyblok-js-client
.
Acknowledgements
A huge thank you goes to the Astro Team. In particular to Tony Sull, who has provided extraordinary support and made automagically rendering Storyblok components a reality.
🔗 Related Links
ℹ️ More Resources
Support
Contributing
Please see our contributing guidelines and our code of conduct.
This project use semantic-release for generate new versions by using commit messages and we use the Angular Convention to naming the commits. Check this question about it in semantic-release FAQ.