Build Your Own Link Hub With Storyblok, Astro and Edgio
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}.

create a new space
Create a new Storyblok space by giving it a name.

Select New Space, Give It A Name and Click Create Space
Click on Create New {1} to get started with creating the Profiles folder.

Create Profiles folder in your content space
Click on Folder {1} to get started with creating the Profiles folder.

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.

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

Click the Profiles folder to start creating each profile
Click on Create New to start creating your first Profile entry.

Click Create New to create your first profile

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.

Click Define to set how a single profile data will look like
Add a Name field to the schema (type Text).

After typing Name under the input, press enter to assign Name as Text type
Add an About field to the schema (type Text).

Similarly, enter About as the Text Type
Add an Image field to the schema (type Asset).

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

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.

Adding social media profiles
Add OG field to the schema (type Asset).

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

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

Select allow external URL and change the file type of Images
Start adding links to the Blocks {1} field and choose the Feature block.

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

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

Change how content in Feature is define by click on Edit Field
Add an Image field to the schema (type Asset).

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

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

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

Similarly, create blocks for Socials

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
.

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.
Resource | Link |
---|---|
Github Example Repo | https://github.com/rishi-raj-jain/link-hub-storyblok-astro-edgio-starter |
Astro Documentation | https://docs.astro.build/en/guides/data-fetching |
Edgio Deploying Guide | https://docs.edg.io/guides/sites_frameworks/getting_started/astro |
Further resources
Resource | Link |
---|---|
Astro | https://astro.build/ |
Storyblok | https://www.storyblok.com/ |
Storyblok SDK for Astro | https://github.com/storyblok/storyblok-astro |
Storyblok SDK Live Demo | https://stackblitz.com/edit/astro-sdk-demo |
Storyblok in the Astro Docs | https://docs.astro.build/en/guides/cms/storyblok/ |
Building Future-Proof High-Performance Websites With Astro Islands And Headless CMS | https://www.smashingmagazine.com/2023/02/building-future-proof-high-performance-websites-astro-islands-headless-cms-storyblok/ |
Storyblok APIs | https://www.storyblok.com/docs/api |