Skip to content

Integrate Svelte with Storyblok

Use Storyblok to manage the content of your Svelte application.

Create a new Svelte project in a few simple steps by following the Creating a project page from the SvelteKit official documentation.

If you already have a Storyblok account, go to app.storyblok.com or log in with GitHub to continue.

Create a new blank space (opens in a new window) to follow the tutorial from scratch, or start from the core blueprint (opens in a new window).

In your terminal, cd into your SvelteKit application and install @storyblok/svelte.

Terminal window
npm install @storyblok/svelte

In the root of your project, create a .env file with the access token from your space.

.env
VITE_STORYBLOK_DELIVERY_API_TOKEN=<YOUR-ACCESS-TOKEN>

In the root layout, initialize the Storyblok client.

src/routes/+layout.js
import { apiPlugin, storyblokInit, useStoryblokApi } from "@storyblok/svelte";
export async function load() {
storyblokInit({
accessToken: import.meta.env.VITE_STORYBLOK_DELIVERY_API_TOKEN,
apiOptions: {
region: 'eu', // Choose the correct region from your Space.
},
use: [apiPlugin],
});
const storyblokAPI = await useStoryblokApi();
return {
storyblokAPI,
};
}

This approach will give access to the storyblokAPI via the parent parameter to all descendant load functions.

Create a src/routes/[...slug]/+page.js file and get access the storyblokAPI client using the parent function.

src/routes/[...slug]/+page.js
/** @type {import('./$types').PageLoad} */
export async function load({ params, parent }) {
const { storyblokAPI } = await parent();
const response = await storyblokAPI.get("cdn/stories/home", {
version: 'draft',
});
return {
story: response.data.story,
};
}

The +page.js file passes the story to the corresponding +page.svelte file’s data prop.

Paste the following code into src/routes/[...slug]/+page.svelte.

src/routes/[...slug]/+page.svelte
<script>
import { StoryblokComponent } from '@storyblok/svelte';
export let data
</script>
<StoryblokComponent blok={data.story.content} />

@storyblok/svelte provides a component to handle your blocks, StoryblokComponent.

Create Page.svelte component to render all stories of the page content type, such as the home story.

src/lib/Page.svelte
<script>
import { StoryblokComponent } from "@storyblok/svelte"
export let blok;
</script>
{#each blok.body as blok}
<StoryblokComponent {blok} />
{/each}

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/lib/Feature.svelte
<script>
export let blok;
</script>
<div class="feature">
<span>{blok.name}</span>
</div>
src/lib/Teaser.svelte
<script>
export let blok;
</script>
<div class="teaser">
<h2>{blok.headline}</h2>
</div>
src/lib/Grid.svelte
<script>
import { StoryblokComponent } from "@storyblok/svelte";
export let blok;
</script>
<div class="grid">
{#each blok.columns as nestedBlok}
<StoryblokComponent blok={nestedBlok} />
{/each}
</div>

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

Add all these new components to the layout file.

src/routes/+layout.js
import { apiPlugin, storyblokInit, useStoryblokApi } from "@storyblok/svelte";
import Teaser from "$lib/Teaser.svelte"
import Feature from "$lib/Feature.svelte"
import Grid from "$lib/Grid.svelte"
import Page from "$lib/Page.svelte"
export async function load() {
storyblokInit({
accessToken: import.meta.env.VITE_STORYBLOK_DELIVERY_API_TOKEN,
apiOptions: {
region: 'eu', // Choose the correct region from your Space.
},
use: [apiPlugin],
components: {
teaser: Teaser,
feature: Feature,
grid: Grid,
page: Page,
}
});
const storyblokAPI = await useStoryblokApi();
return {
storyblokAPI,
};
}

Run the server and visit the site in your browser.

Terminal window
npm run dev