---
title: Content Modeling in Eleventy
description: Learn how to handle custom blocks, render rich text, and use story references to manage content across your Eleventy project.
url: https://storyblok.com/docs/guides/eleventy/content-modeling
---

# Content Modeling in Eleventy

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

## Setup

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

  

> [!NOTE]
> Learn more about fields in the [concept](/docs/concepts/fields).

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.

## Fetch and list articles

Create a new `articles.js` data file to get all stories from this new content type.

src/\_data/articles.js

```javascript
import storyblok from '../_utils/storyblok.js';
import { richTextResolver } from '@storyblok/richtext';

const { render } = richTextResolver();

export default async function pages() {
  const response = await storyblok.getAll('cdn/stories', {
    version: 'draft', // or "published"
    starts_with: 'articles',
    content_type: 'article',
  });

  return response.map(story => {
    const permalink = `/${story.full_slug}/`;
    const title = story.content.title;
    const content = render(story.content.content);

    return {
      permalink,
      title,
      content,
    };
  })
}
```

To render rich text fields, install the `@storyblok/richtext` package and pass the `content` field from the story to its `render` method.

> [!NOTE]
> Learn more about handling rich text in Storyblok in the fields concept and the `@storyblok/richtext` reference.

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`.

> [!NOTE]
> Learn more about parameters and filter queries in the [Content Delivery API documentation](https://www.storyblok.com/docs/api/content-delivery/v2).

Create an `article_overview.md` page with the following content:

src/article-overview.md

```html
---
layout: 'layouts/base.liquid'
title: 'Article Overview'
permalink: 'article-overview/'
---

<main>
  <h1>Article Overview</h1>
  <ul>
    {%- for article in articles %}
      <li>
        <a href="{{ article.permalink }}">{{ article.title }}</a>
      </li>
    {% endfor -%}
  </ul>
</main>
```

Now, the `/article-overview` route show a list of links to all articles.

## Create the articles block

Add a new `article.liquid` layout file and an `articles.md` content file to render the new article content type.

src/\_includes/layouts/article.liquid

```html
---
layout: 'layouts/base.liquid'
---

<main>
  <h1>{{ title }}</h1>
  {{ content }}
</main>
```

src/articles.md

```html
---
layout: 'layouts/article.liquid'
pagination:
  data: articles
  size: 1
  alias: article
eleventyComputed:
  title: '{{ article.title }}'
permalink: '{{ article.permalink }}'
---

{{ article.content }}
```

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

## Handle referenced stories

In the `pages.js` data file, set the `resolve_relations` parameter to get the full object response of referenced stories.

src/\_data/pages.js

```javascript
import storyblok from '../_utils/storyblok.js';
import Feature from '../_components/feature.js'
import Teaser from '../_components/teaser.js'
import Grid from '../_components/grid.js'
import FeaturedArticles from '../_components/featured_articles.js'

export default async function pages() {
  const response = await storyblok.getAll('cdn/stories', {
    version: 'draft', // or "published"
    content_type: 'page',
    resolve_relations: "featured-articles.articles"
  });

  return response.map(story => {
    const permalink = story.slug === 'home' ? '/' : `/${story.full_slug}/`;
    const name = story.name;
    const body = story.content.body
      .map(blok => {
        switch (blok.component) {
          case 'feature':
            return Feature(blok);
          case 'teaser':
            return Teaser(blok);
          case 'grid':
            return Grid(blok);
         case 'featured-articles':
           return FeaturedArticles(blok);
          default:
            throw new Error(`Could not resolve ${blok.component} block.`);
        }
      })
      .join('');

    return {
      permalink,
      name,
      body,
    };
  })
}
```

> [!NOTE]
> Learn more in the [references concept](https://www.storyblok.com/docs/concepts/references) documentation.

Next, create a new `src/_components/featured_articles.js` component.

src/\_components/featured\_articles.js

```javascript
import { storyblokEditable } from '@storyblok/js';

function FeaturedArticles(blok) {
  const attrs = storyblokEditable(blok);

  return (
    `<section class="storyblok__outline" data-blok-uid="${attrs['data-blok-uid']}" data-blok-c="${attrs['data-blok-c']}">
      <h2>Featured Articles</h2>
      <ul>
      ${blok.featured_articles.map((article) => {
        return (
          `<li>
            <a href="${article.full_slug}">${article.content.title}</a>
          </li>`
        );
      })}
      </ul>
    </section>`
  );
}

export default FeaturedArticles;
```

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

## Related resources

[Eleventy Pagination API](https://www.11ty.dev/docs/pagination/)

[Eleventy Layouts](https://www.11ty.dev/docs/layouts/)

[Eleventy Data Files](https://www.11ty.dev/docs/data-global/)

[Iterations in Liquid](https://shopify.github.io/liquid/tags/iteration/)

[Concept: Fields](/docs/concepts/fields)

[Concept: References](/docs/concepts/references)

[@storyblok/richtext Package Reference](https://www.storyblok.com/docs/libraries/js/richtext)

  

## Pagination

-   [Previous: Dynamic Routing in Eleventy](/docs/guides/eleventy/dynamic-routing)
