Creating global components and referencing them in Storyblok

Contents

In Storyblok you’re able to define your content structure in smaller pieces, so called Components if a pure flat structure, which is also possible, is not enough. Think of something that is more complex than an blog article which already works with only one markdown field. Let’s think about a landing page with header and footer being the same on every page, and sometimes you might also have things like newsletter, or form sections that you want for some pages, right? Let’s see how you can achieve both with Storyblok. Make sure to have an account and create your space. We will jump right into setting up the structure as we assume that you’re already have done that.

What we’re about to do

The use-case for this would be content that is repeated on more than one site, and you want to keep the content the same throughout. Depending on having them on all pages or only on specific once you can either load them directly in your implementation – or load them as part of your reference - your choice.

  1. Creating a folder that contains all our global entries
  2. Define a content type for our global components
  3. Create a field in that content type that holds our component
  4. Create a reference component so we can link them
  5. Check out our resolve_relations API feature to link to the global components

Follow along guide

We will set-up a folder in Storyblok. During the creation of that new folder you’re able to define a content-type, this content type will be the holder for our new global components, so let’s go with global as the name for the entry that’s going to hold our components. We will also enable the option that nobody is allowed to change the content type in the global folder, so we only have entries of that type in here. In the same step we will also make sure to use the default content type option so global is already selected.

Folder creation with new - global - content type

Once you’ve created that folder, we can now create our first entry in there. We will have to make sure that we’re going to use the content type global while we create that new entry. Since we’ve disabled the possibility of changing the content type for the folder this should already be on global by default. Enter any name that you want for the Entry itself, but make sure this name will explain the content of the global component in the entry to your editors. We are going for “Newsletter Section” as this is the one we want to have on multiple pages and reference to it.

Entry creation dialog

Next step will be to set-up the actual field in the entry that holds our component, for this we will click on “Define Schema” and adding a new field called global of the type blok. Pressing save will allow you to now add new components of any time in there, if you want to limit that you can go back to “Define Schema” and use the advanced option to limit the number and type of components (and even component groups) to be added as global components.

New field component with the type bloks

Once you’ve done that, we will be able to add the actual component that you want to be able to reference from everywhere. We will go for our already existing component “newsletter-section”, feel free to use the one of yours or create a new one. If you’re using a new space you will also find a teaser component that you can use as an example.

Adding a new component to your global entry

Creating the reference component

Now, as we do have the structure defined for our global components, we will move on to referencing them. To reference such an entry all we have to do is to define a field of the type single-option or multi-options in existing components or create a new component which only use-case is to reference to those.

First we will navigate to the Components menu where we will hit “New” on the top right corner. You will be prompted with an input field to name the component, we will use global_reference. After confirming the name, we will add a new field called reference and hit “Add”.

Creating the global reference component and adding the field

You will now be able to choose the field type, the one we want in this example is single-option, however if you want to reference to multiple global components at once you can also use the multi-option the same way. Once you’ve selected single-option you can choose “Stories” as your source. Below that drop down of source types we will also enter global/ for “Path to folder of stories”. Once that done, we will hit the “Save schema” button on the top right corner.

Configuring the reference field

You can now use that global reference in every Bloks field as you would with your normal component. Now however all we will do in there is to select the entry that contains the component we want to display at this place, in our example: the newsletter section.

Using the global reference component and selecting the newsletter section

Once pressing Save, you will already be able to consume the reference: https://api.storyblok.com/v1/cdn/stories/home?version=published&token=9Nr61DDCn4yCTKYr4EKsfwtt&cv=1578935063

{
  "story": {
    "name": "Home",
    "uuid": "d0c3cd93-0731-445c-a8dd-e990b059296d",
    "content": {
      "body": [
        {
          "headline": "Hello world!",
          "component": "teaser"
        }, 
        {
          "component": "global_reference",
          "reference": "ace83ae3-a0fb-4a56-9008-5abb3ccc49b3"
        }
      ],
      "component": "page"
    },
    "slug": "home",
    ...
  }
}

Resolving the relationship with the API

You will notice that we’re only storing the UUID of referenced Story and you would now already be able to load that specific entry by its UUID. However, what we actually want to do here is to have that content included in the initial response and not have to load it with a second request. Since we’re now using a generic reference component for all our global entries, all we have to do is to use the resolve_relations as an additional query parameter:

https://api.storyblok.com/v1/cdn/stories/home?
    version=published&
    token=9Nr61DDCn4yCTKYr4EKsfwtt&
    cv=1578935063&
+   resolve_relations=global_reference.reference

And our response will result in us having the UUID of the global_reference component being resolved to the actual whole Story entry including the component we want to have.

{
  "story": {
    "name": "Home",
    "uuid": "d0c3cd93-0731-445c-a8dd-e990b059296d",
    "content": {
      "body": [
        {
          "headline": "Hello world!",
          "component": "teaser"
        }, 
        {
          "component": "global_reference",
-          "reference": "ace83ae3-a0fb-4a56-9008-5abb3ccc49b3"
+          "reference": {
+            "name": "Newsletter Section",
+            "created_at": "2020-01-13T17:59:40.183Z",
+            "published_at": "2020-01-13T18:02:17.725Z",
+            "alternates": [
+              
+            ],
+            "id": 5574308,
+            "uuid": "ace83ae3-a0fb-4a56-9008-5abb3ccc49b3",
+            "content": {
+              "_uid": "d9881cb2-b902-4d3c-b70e-81a6e4c67117",
+              "global": [
+                {
+                  "_uid": "83046285-798c-4884-b206-e7c4386c2e11",
+                  "Image": "//a.storyblok.com/f/73159/3244x1184/cc4c5bb0b3/_demo1.jpg",
+                  "Headline": "Let's stay in touch!",
+                  "component": "Newsletter Section",
+                  "Subheadline": "We won't spam – promise!"
+                }
+              ],
+              "component": "global"
+            },
+            "slug": "newsletter-section",
+            "full_slug": "global/newsletter-section",
+            "sort_by_date": null,
+            "position": 0,
+            "tag_list": [
+              
+            ],
+            "is_startpage": false,
+            "parent_id": 5574306,
+            "meta_data": null,
+            "group_id": "926619a1-d7a0-497a-a5d1-be2a0e6b5db5",
+            "first_published_at": "2020-01-13T18:02:17.725Z",
+            "release_id": null,
+            "lang": "default",
+            "path": null
+         }
        }
      ],
      "component": "page"
    },
    "slug": "home",
    ...
  }
}

Wrap up

You’re now able to create mutliple global components and re-use them on other places just like that. Using that method for components you have on every site is something we would not recommend – we would recommend loading them once and store them and reuse them from there. A good example for that would be Header and Footer which can be on every page and you would be better off sending once additional request once, rather them having the whole content included on every request.

Dominik Angerer

Author

Dominik Angerer

A web performance specialist and perfectionist. After working for big agencies as a full stack developer he founded Storyblok. He is also an active contributor to the open source community and one of the organizers of Stahlstadt.js.