Add a headless CMS with Live Preview to SvelteKit in 5 Minutes

Contents
    Try Storyblok

    Storyblok is the first headless CMS that works for developers & marketers alike.

    This short tutorial will show you how to integrate the Storyblok API into a SvelteKit app. We will also enable the real-time editing experience in the Visual Editor with the Storyblok JS Bridge - so that you can see your changes right away.  At the end of this article, you will have a SvelteKit application that renders components filled with data from Storyblok. 

    If you don't know what a Headless CMS is or what Storyblok does, please read first the Storyblok Guide.

    Live Demo:

    If you’re in a hurry, try the live demo in Stackblitz!

    Environment Setup

    Requirements

    To follow this tutorial, make sure to meet these requirements:

    Create a Sveltekit project

    Let’s create a Sveltekit project following the official installation guide

    npm init svelte@next my-app 
    cd my-app
    npm install
    npm run dev

    When creating your new project, you will be asked if you want to set up some basic tooling like TypeScript. For the purpose of our project, you can select the basic skeleton project without Typescript and Playwright browser testing. We also don't require Eslint or Prettier, but feel free to set these things up according to your needs. 

    Hint:

    There is a Sveltekit Plugin for VS Code that helps with syntax highlighting.

    You should now be able to see the SvelteKit App in your browser when you open https://localhost:3000

    https://localhost:3000/
    Start screen of SvelteKit App

    Configuration of the space

    Create a new space in the Storyblok app by clicking + Create new space and choosing the Create new space {1} option. Pick a name for it {2}.

    storyblok.com
    Creating a new space in the storyblok app
    1
    2

    Now, a Storyblok space with sample content has been created. If you open the Home story you will see the Visual Editor on your screen:

    storyblok.com
    Welcome screen in the visual editor
    Hint:

    Understand what represents Story in our Storyblok Guide.

    Enabling the Visual Editor 

    To see your website in the Storyblok Visual Editor you need to set the default environment URL. For that, in your space, open Settings > Visual Editor {1} and set the Location field to https://localhost:3000/ {2}:

    storyblok.com
    Configuring default environment to localhost
    1
    2

    Now go back to the Home story under the Content section. You'll see the Visual Editor when you open it, but you won't see your SvelteKit application yet. 

    Setting up a HTTPS Connection

    If you are working with the Visual Editor V2, you’ll need to make a slight change to your svelte.config.js and add the https: truethere in the server configuration. This is because the V2 requires a secure connection through HTTPS. 

    const config = {
      kit: {
        vite: {
          server: {
            https: true
          }
        },
      },
    };

    Now, open the Config tab {1} on the right-hand form, and set the Real Path to “/” {2}. Save, and if you’re still running your SvelteKit app, you will see it now in the Visual Editor.

    storyblok.com
    Sveltekit Start screen in the Visual Editor

    Connecting SvelteKit to Storyblok

    First of all, let’s install @storyblok/svelte, our official SDK for all things Svelte & SvelteKit: 

    npm install @storyblok/svelte
    # yarn add @storyblok/svelte

    It allows you to interact with Storyblok API and enable the real-time editing experience. Let's configure it.

    First of all, you need to grab your access token from your space Settings > Access Token:

    storyblok.com
    Adding the access token

    Now let’s create a __layout.svelte file in the src/routes folder of our SvelteKit app. Here we can initialize the library, add the ApiPlugin and the access token of our Storyblok space: 

    <script context="module">
        import { storyblokInit, apiPlugin } from "@storyblok/svelte";
      
        storyblokInit({
          accessToken: "your-preview-token",
          use: [apiPlugin]
        });
        
    </script>
      
    <main>
        <slot/>
    </main>

    storyblokInit sets up the connection with the space. It initializes the Storyblok Bridge, that allows us to enable the real-time editing experience inside the Visual Editor. The function also provides an instance of the Storyblok API client that we can use to retrieve content from Storyblok.

    If you are planning to use the Storyblok API client to call the REST API, make sure to include the ApiPlugin when initializing the storyblokInit() function.

    Now, add all the components that you want to link to Storyblok in the components object in the storyblokInit() function. This will link them to their representation in the Storyblok space. You can load all of them at the same time by adding them to the list, like so:

    <script context="module">
      import { storyblokInit, apiPlugin } from "@storyblok/svelte";
      import Feature from '../components/Feature.svelte';
      import Grid from '../components/Grid.svelte';
      import Page from '../components/Page.svelte';
      import Teaser from '../components/Teaser.svelte';
    
      storyblokInit({
        accessToken: "your-preview-token",
        use: [apiPlugin],
        components: {
          feature: Feature,
          grid: Grid,
          page: Page,
          teaser: Teaser,
        },
      });
      
    </script>
    <main>
        <slot/>
    </main>

     

    Fetching the Content 

    Now you can use the useStoryblokApi() in the index.svelte to get your stories from the Storyblok CDN API: 

    
    <script context="module">
      import { useStoryblokApi } from "@storyblok/svelte";
      
      export async function load(){
        const storyblokApi = useStoryblokApi();
        const { data } = await storyblokApi.get("cdn/stories/home", { version: "draft",
        });
        return {
          props:{ story: data.story } 
        }
      }
    </script>
    Hint:

    Make sure to adjust the path according to your content structure if you structured your project differently.

    Listening to changes in the Visual Editor

    To enable the life editing experience, you can use the useStoryblokBridge() function provided from @storyblok/svelte: 

    <script>
      import { onMount } from "svelte";
      import {useStoryblokBridge, StoryblokComponent } from "@storyblok/svelte";
      
      export let story;
      
      onMount(() => {
        useStoryblokBridge(story.id, (newStory) => (story = newStory));
        });
    </script>
      
    <div>
      {#if story}
        <StoryblokComponent blok={story.content} />
      {/if}
    </div>

    Adding Components

    As you may have already seen, the content in Storyblok is structured as components (or blocks). We can have stories, that are composed of different components. You can see an example in the Home story of our new space.

    Hint:

    If you want to learn more about how the content is structured in Storyblok, you can read this guide.

    In our example, we have created 4 example components in the src/components folder: 

    • Feature

    • Grid

    • Page

    • Teaser

    To make your components editable in the Storyblok Visual Editor, you have to add the use:storyblokEditable={blok} action to the root of each component that you are loading in your storyblokInit. For example, in Teaser.svelte:

    
    <script>
    import { storyblokEditable } from "@storyblok/svelte";
    export let blok;
    </script>
    <div use:storyblokEditable={blok}>
        { blok.headline }
    </div>

    Use the StoryblokComponent to load them by passing the blok property.

    Hint:

    The blok is the actual blok data coming from Storyblok’s Content Delivery API.

    One last thing

    Please note that currently, you need to add 'axios' to the optimizeDeps object in your svelte.config.js.:

    import adapter from '@sveltejs/adapter-auto';
    
    const config = {
      kit: {
        adapter: adapter(),
        vite: {
          optimizeDeps: {
            include: ['axios'],
          },
        },
      },
    };
    export default config;

    And that’s it. When you now check out your story in the Visual Editor, the Storyblok JS Bridge is enabled, and you can make real-time changes: 

    storyblok.com
    Visual Editor with JS Bridge Enabled

    Wrapping up

    And that’s it - congrats for making it until this point! You should now have a fully functioning SvelteKit app all set up and ready to go with Storyblok, including the real-time changes and Visual Editor.