Skip to main content

Build Your Own Link Hub With Storyblok, Astro and Edgio

Contents
    Try Storyblok

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

    This guide describes how to create and deploy your own Link Hub built with Storyblok & Astro to Edgio. Clone the repo link-hub-storyblok-astro-edgio-starter to get the entire setup.

    Set up Storyblok space

    To set up a Storyblok space, log in to your account or create a new one, and click on New Space {1}.

    app.storyblok.com
    create new space
    1

    create a new space

    Create a new Storyblok space by giving it a name.

    app.storyblok.com
    Select New Space, Give It A Name
    1
    2

    Select New Space, Give It A Name and Click Create Space

    Click on Create New {1} to get started with creating the Profiles folder.

    app.storyblok.com
    create profiles folder
    1

    Create Profiles folder in your content space

    Click on Folder {1} to get started with creating the Profiles folder.

    app.storyblok.com
    Click Folder to start creating a collection of Profiles
    1

    Create a collection of Profiles

    Imagine Storyblok's folder as a collection of items, and each Storyblok entry being an item itself. We'll be creating two folders: Profiles and Profile. Each entry that lives inside Profiles represents an individual Author or a Post.

    After typing in the Name, click on Add New as the content type and give it a personalized Name (here: Link Hub Profile Links) as we'll be giving it our own blueprint. Click save to create a Profiles folder.

    app.storyblok.com
     Select the content type to “Add new” and give it a personalised name
    1

    Select the content type to “Add new” and give it a personalised name

    app.storyblok.com
    start creating each profile
    1

    Click the Profiles folder to start creating each profile

    Click on Create New to start creating your first Profile entry.

    app.storyblok.com
    create your first profile
    1

    Click Create New to create your first profile

    app.storyblok.com
    create your first profile
    1

    Select the personalized name of the content type you gave while creating the folder and create the first story

    Click on Define {1} to start defining the Profile schema.

    app.storyblok.com
    Define the profile schema
    1

    Click Define to set how a single profile data will look like

    Add a Name field to the schema (type Text).

    app.storyblok.com
    Adding a name field
    1

    After typing Name under the input, press enter to assign Name as Text type

    Add an About field to the schema (type Text).

    app.storyblok.com
    Adding an about field
    1

    Similarly, enter About as the Text Type

    Add an Image field to the schema (type Asset).

    app.storyblok.com
    Adding an image field
    1
    2

    Now, type in Image that’d be associated with a user and click on icon near it. Change the item to being an asset.

    For all the Links {1} that’ll be visible to the user, let's create a Blocks {2} so that we can insert as many associative links as we want to

    app.storyblok.com
    Adding a links field
    1
    2

    Adding a links field

    For all the Socials {1} that’ll be visible to the user, let's also use a Blocks {2} field so that we can insert as many associative socials as we want to.

    app.storyblok.com
    Adding social media profiles
    1
    2

    Adding social media profiles

    Add OG field to the schema (type Asset).

    app.storyblok.com
    add OG field
    1
    2

    Adding an OG image field

    Click on the Settings Icon (Edit Field) {1} to change how the Image field is set up

    app.storyblok.com
    Allowing external URLs in the Image field
    1

    Allowing external URLs in the Image field

    Click on Allow external URL {1} and select Images {2} to limit the Asset type to images and also, allow linking to external URLs

    app.storyblok.com
    Select allow external URL and change the file type of Images
    1
    2

    Select allow external URL and change the file type of Images

    Start adding links to the Blocks {1} field and choose the Feature block.

    app.storyblok.com
    Adding links
    1

    Adding links

    Click on the Feature {1} block created above and let’s change what each link can contain.

    app.storyblok.com
    Click on the Feature button in the Links column
    1

    Click on the Feature button in the Links column

    Click on Settings Icon (Edit Field) {1} to access the schema of the Feature block

    app.storyblok.com
    Change how content in Feature is define by click on Edit Field
    1

    Change how content in Feature is define by click on Edit Field

    Add an Image field to the schema (type Asset).

    app.storyblok.com
    Create an Image type to associate with each link that’ll be present in the final view
    1
    2

    Create an Image type to associate with each link that’ll be present in the final view

    Add a URL field to the schema as the (type URL).

    app.storyblok.com
    Create a field named URL of type URL where the link will point to when clicked
    1
    2

    Create a field named URL of type URL where the link will point to when clicked

    app.storyblok.com
    After clicking and save filling the information, this is how it looks once filled in

    After clicking and save filling the information, this is how it looks once filled in

    app.storyblok.com
    Similarly, create blocks for Socials
    1

    Similarly, create blocks for Socials

    app.storyblok.com
    This is how the Socials feature will look once you’ve enabled all the fields created above

    This is how the Socials feature will look once you’ve enabled all the fields created above

    Next, obtain the Preview {1} API key (further referred to as STORYBLOK) shown in the tab Access Tokens of Settings. Obtain the token from the list as STORYBLOK.

    app.storyblok.com
    Finally, with that done, obtain the preview token to be used in your code
    1

    Finally, with that done, obtain the preview token to be used in your code

    Set up Astro with Edgio

    To set up, just clone the app repo and follow this tutorial to learn everything that's in it. To fork the project, run:

    git clone https://github.com/rishi-raj-jain/link-hub-storyblok-astro-edgio-starter
    cd link-hub-storyblok-astro-edgio-starter
    yarn install


    After these steps, you should be able to start the local environment using the following command:

    yarn run edgio:dev

    Implementing Data Fetching and Revalidation

    In this section, we'll be diving deep into how the data fetching and revalidation for the user profiles is done. We make constant use of Stale While Revalidate on the Edge to achieve 100% cache hit rates, and @astro/storyblok to fetch and display data statically.

    getUserInfo: Fetching the user profile

    The getUserInfo function uses Storyblok's useStoryblokApi hook to make an API request to the relevant user profile page, identified by a unique slug. If the story is present, the function extracts the name, image, about, links, social media profiles, and lastly SEO first open graph image from the returned data. The function maps the links and social media profiles to arrays and returns all the extracted data in an object with a code of 1.

    Furthermore, If the story is not present or there is an error, the function returns an object with a code of 0 so that then the user can be redirected to 404 automatically.

    // File: lib/user.js
    
    import { useStoryblokApi } from '@storyblok/astro'
    
    export async function getUserInfo(slug) {
      try {
        const storyblokApi = useStoryblokApi()
        // Append cdn/stories/ before your full slug path
        const { data } = await storyblokApi.get(`cdn/stories/profiles/${slug}`)
        // If the story is there, return the required data
        if (data.story) {
          const { name, content } = data.story
          const { About, Image, Links, Socials, OG } = content
          return {
            name,
            image: Image.filename,
            about: About,
            links: Links.map((i) => [i.Name ?? i.name, i.URL.url, i.Image.filename]),
            socials: Socials.map((i) => [i.Name ?? i.name, i.URL.url]),
            og: { image: OG.filename },
            code: 1,
          }
        }
        return { code: 0 }
      } catch (e) {
        console.log(e.message || e.toString())
        return { code: 0 }
      }
    }

    Implementing stale-while-revalidate on the edge for all the user profiles

    The following code describes how to use the concept of Stale While Revalidate to achieve 100% cache hit rates. In the code (in routes.js), the router.match function is used to match all the user profiles (that start with /me/). Inside the cache method, we prevent caching the page in browser and enable only edge caching to always serve users fast and with the latest content. The edge option is set to maxAgeSeconds: 1 to ensure that the data is cached for only a second. The staleWhileRevalidateSeconds option is set to be a year to allow the data to be served directly from the cache while the cache is being refreshed.

    // File: routes.js
    
    // User path(s)
    router.match('/me/:path', ({ cache, removeUpstreamResponseHeader }) => {
      // Remove the cache-control header from Astro's standalone server
      removeUpstreamResponseHeader('cache-control')
      // Disable in browser caching, and use Edgio's edge to use SWR
      cache({
        edge: {
          maxAgeSeconds: 1,
          staleWhileRevalidateSeconds: 60 * 60 * 24 * 365,
        },
        browser: false,
      })
    })

    Using Stale While Revalidate can help to improve the performance of the app by reducing the load on the server and providing faster responses to the user.

    Creating dynamic user profiles on the fly

    Astro makes it super easy to set up dynamic routes. In the app, you'd find src/pages/me/[slug].astro, which maps pages that start with /me/. Examples include /me/user-1 and /me/some-new-user.

    Fetching user profiles

    We fetch the data for the current user by making use of the slug query parameter extracted out of Astro params, and call the getUserInfo function (as described above) to obtain all the related user data. In case of not found or an error, we redirect the visitor to a 404:

    // File: src/pages/me/[slug].astro
    
    // Extract slug query
    const { slug } = Astro.params
    
    // Get data from Storyblok using the getUserInfo function
    const {
      name: userName,
      image: userImage,
      links = [],
      socials = [],
      about = '',
      og = {},
      background = {},
      code = 1,
    } = await getUserInfo(userSlug)
    
    // In case the code: 0 is recevied, redirect to a 404
    if (code === 0) {
      return Astro.redirect('/404')
    }

    Deploy from CLI

    You can do a production build of your app and test it locally using:

    yarn run edgio:build && yarn run edgio:production

    Deploying requires an account on Edgio. Sign up here for free. Once you have an account, you can deploy to Edgio by running the following command in the root folder of your project:

    yarn run edgio:deploy

    Now we are done with the deployment! Yes, that was all. You should see something like this in the console:

    Go ahead! Change content and publish it on Storyblok, and browse the /me/user-slug route of your website to look for changes (yes, revalidation works just like that!).

    Summary

    In this tutorial, we learned how to build our own Link Hub with Storyblok CMS in a Astro project and deploy it to Edgio.

    Further resources