Skip to content

Content Modeling in Svelte

Learn how to handle different content type and nestable blocks, render rich text, and use story references to manage content globally.

In the existing space, create the following blocks:

  • An article content type block with the following fields:
    • title: Text
    • content: Rich text
  • An article-overview content type block with the following field:
    • title: Text
  • A featured-articles nestable block with the following field:
    • articles: References

Next, create an Articles folder, open it, and create the following stories:

  • A few stories that use the article content type.
  • An article overview story with a article-overview content type. Select the option Define as root for the folder.

Finally, add the featured-articles block to the body field of the Home story, and select articles to feature.

Create new +page.js and +page.svelte files at src/routes/article-overview to get all stories from this new content type.

src/routes/article-overview/+page.js
/** @type {import('./$types').PageLoad} */
export async function load({ params, parent }) {
const { storyblokAPI } = await parent();
const articles = await storyblokAPI.getAll('cdn/stories', {
version: 'draft',
starts_with: 'articles',
content_type: 'article',
});
return {
articles
};
}
src/routes/article-overview/+page.svelte
<script>
export let data
</script>
<h1>Article Overview</h1>
<ul>
{#each data.articles as article}
<li>
<a href="{article.full_slug}">{ article.content.title }</a>
</li>
{/each}
</ul>

Using the starts_with parameter, only stories from the “Articles” folder are fetched. Using the content_type parameter, the results are restricted to stories of the content type article.

Now, the /article-overview route shows a list of links for all articles.

Add a new Article.svelte component to render the new article content type.

src/lib/Article.svelte
<script>
import { renderRichText } from '@storyblok/svelte';
const { blok } = $props()
let renderedRichText = $derived(renderRichText(blok.content));
</script>
<h1>{blok.title}</h1>
<div>{@html renderedRichText}</div>

To render rich text fields, use the renderRichText helper provided by the @storyblok/svelte module.

Update the layout file to add the new content type.

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';
import Article from '$lib/Article.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,
article: Article,
},
});
const storyblokAPI = await useStoryblokApi();
return {
storyblokAPI,
};
}

When clicking on links present in the article overview page, an article page renders correctly.

In the +page.js file, set the resolve_relations parameter to get the full object response of referenced stories.

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/${params.slug || "home"}`, {
version: 'draft',
resolve_relations: "featured-articles.articles"
});
return {
story: response.data.story,
};
}

Next, create a new FeaturedArticles.svelte component.

src/lib/FeaturedArticles.svelte
<script>
import { storyblokEditable } from '@storyblok/svelte'
export let blok;
</script>
<section {...storyblokEditable(blok)}>
<h2>Featured Articles</h2>
<ul>
{#each blok.articles as article}
<li>
<a href="{article.full_slug}">
{article.content.title}
</a>
</li>
{/each}
</ul>
</section>
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';
import Article from '$lib/Article.svelte';
import FeaturedArticles from '$lib/FeaturedArticles.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,
article: Article,
['featured-articles']: FeaturedArticles,
},
});
const storyblokAPI = await useStoryblokApi();
return {
storyblokAPI,
};
}

Now, this component will render links to the featured articles in the homepage of your project.


Was this page helpful?

What went wrong?

This site uses reCAPTCHA and Google's Privacy Policy (opens in a new window) . Terms of Service (opens in a new window) apply.