Almost EVERYONE who tried headless systems said they saw benefits. Download the state of CMS now!

Storyblok now on AWS Marketplace: Read more

O’Reilly Report: Decoupled Applications and Composable Web Architectures - Download Now

Empower your teams & get a 582% ROI: See Storyblok's CMS in action

Skip to main content

Creating global components and referencing them in Storyblok

Try Storyblok

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

  • Home
  • Tutorials
  • Creating global components and referencing them in Storyblok

In Storyblok, you can define your content structure in smaller pieces, so-called Components, if a purely flat structure, which is also possible, is not enough. Think of something more complex than a blog article that already works with only one markdown field. Let's think about a landing page with the same header and footer on every page. Sometimes, you might also have things like a 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. Assuming you already have done that, we will jump into setting up the structure.

Section titled What we're about to do What we're about to do

The use-case for this would be content repeated on multiple sites, and you want to keep the content the same throughout. Depending on whether you have them on all pages or only on specific ones, 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

Section titled Follow along guide 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 can change the content type in the global folder, so we only have entries of that type 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 must ensure 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 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 the "Newsletter Section" as this is the one we want to have on multiple pages and reference to it.

Entry creation dialog

The 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 add a new field called global of the type blok. Pressing "Save" will allow you to add new components anytime. 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) 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, the newsletter-section. Feel free to use one of yours or create a new one. If you're using a new space, you will also find a teaser component you can use as an example.

Adding a new component to your global entry

Section titled Creating the reference component Creating the reference component

Now that we have the structure defined for our global components, we will reference 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 the Block Library menu and hit "New" in 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."

hint:

In this case, you can choose the Global Reference Field as this field-type already locks the Source to Stories by default. For content editors, using Global Reference Field might be straightforward.


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 multiple global components simultaneously, you can use the multi-option similarly. 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 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 there is 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/v2/cdn/stories/home?
version=published&token={YOUR_ACESS_TOKEN}&cv=1678438739
    

This will be your response.

        
      {
    "story": {
        "name": "Home",
        "uuid": "e8a66150-db64-4f32-b47f-36981a3ba81b",
        "content": {
            "_uid": "8e3a9b79-112f-4650-a9e6-763ffad817ac",
            "body": [
                {
                    "_uid": "95ac4a37-76a9-40e0-907b-d812980f7afb",
                    "headline": "Hello world!",
                    "component": "teaser"
                },
                {
                    "_uid": "a19e0e66-4ac9-475b-8256-9b594238a3e5",
                    "component": "global_reference",
                    "reference": "797154fd-2c40-4146-81a6-dfe65b99de98"
                }
            ],
            "component": "page"
        },
        "slug": "home",
    ...
    }
}
    

Section titled Resolving the relationship with the API 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 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 use the resolve_relations as an additional query parameter:

        
      https://api.storyblok.com/v2/cdn/stories/home?
    version=published&
    token={YOUR_ACESS_TOKEN}&
    cv= 1678438739&
+   resolve_relations=global_reference.reference
    

Our response will result in us having the UUID of the global_reference the component being resolved to the actual whole Story entry in a rels array.

        
      {
    "story": {
        "name": "Home",
        "uuid": "e8a66150-db64-4f32-b47f-36981a3ba81b",
        "content": {
            "_uid": "8e3a9b79-112f-4650-a9e6-763ffad817ac",
            "body": [
                {
                    "_uid": "95ac4a37-76a9-40e0-907b-d812980f7afb",
                    "headline": "Hello world!",
                    "component": "teaser"
                },
                {
                    "_uid": "a19e0e66-4ac9-475b-8256-9b594238a3e5",
                    "component": "global_reference",
                    "reference": "797154fd-2c40-4146-81a6-dfe65b99de98"
                }
            ],
            "component": "page"
        },
        "slug": "home"
    },
    "cv": 1678439961,
    "rels": [
        {
            "name": "Newsletter Section",
            "uuid": "797154fd-2c40-4146-81a6-dfe65b99de98",
            "content": {
                "_uid": "bd110835-d716-462a-b3f4-97d883c8f3d6",
                "global": [
                    {
                        "_uid": "0596bc27-ccee-4827-a81b-4fbac572e6a0",
                        "Image": {
                            "id": 7455384,
                            "filename": "https://a.storyblok.com/f/204814/2880x1680/1d01157973/storyblok_v2_create_new_story.png"
                        },
                        "Headline": "Let's stay in touch!",
                        "component": "newsletter-section",
                        "Subheadline": "We won't spam – promise!"
                    }
                ],
                "component": "global"
            },
            "slug": "newsletter-section"
        }
    ],
    "links": []
}
    

Section titled Wrap up Wrap up

You can now create multiple global components and reuse them in other places like that. Using that method for components you have on every site is something we would not recommend – we would recommend loading them once, storing them, and reusing them from there. A good example of that would be Header and Footer which can be on every page, and you would be better off sending one additional request once rather them having the whole content included on every request.

Authors

Dominik Angerer

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 Scriptconf and Stahlstadt.js.

Dipankar Maikap

Dipankar Maikap

Dipankar is a seasoned Developer Relations Engineer at Storyblok, with a specialization in frontend development. His expertise spans across various JavaScript frameworks such as Astro, Next.js, and Remix. Passionate about web development and JavaScript, he remains at the forefront of the ever-evolving tech landscape, continually exploring new technologies and sharing insights with the community.