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

Integrate Svelte with Storyblok

Use Storyblok to manage the content of your Svelte application.

This guide has been tested with the following package versions:

  • svelte@5.0.0
  • @sveltejs/kit@2.16.0
  • @storyblok/svelte@5.0.2
  • node@22.13.0

Setup

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

If you don’t already have a Storyblok space, create one at app.storyblok.com and add some content to the home story.

Use the npm create vue command and opt-out of all optional add-ons.

Installation

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

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>

Learn how to get an access token for your Storyblok project.

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.

Fetch a single story

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>

{#each data.story.content.body as blok}
  <StoryblokComponent {blok} />
{/each}

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

Import that component, use a Svelte {#each} block to iterate over your array, and render each Storyblok block with the StoryblokComponent.

Note that Svelte blocks (e.g. {#each}, {#for} and {#if}) are are not related to Storyblok blocks (e.g. feature, hero, and grid). Svelte blocks are templating utilities. Storyblok blocks are pieces of content.

Create and register blocks

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}

All content in Storyblok is made of blocks. The content of each story is a block, and each component in the content is a nested block.

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.

npm run dev