Build Your Own Showcase Gallery With Storyblok, SvelteKit and Edgio
Storyblok is the first headless CMS that works for developers & marketers alike.
This guide describes how to create and deploy your own Showcase Gallery built with Storyblok & SvelteKit to Edgio. Clone the repo showcase-gallery-storyblok-sveltekit-edgio-starter to get the entire setup.
Create a new Storyblok space by giving it a name.
Get started with creating the Templates
folder.
- Click on Create new {1} button.
- Next, click the Folder {2} button to start creating the Templates folder.
Imagine Storyblok's folder as a collection of items; each Storyblok entry is an item itself. We'll be creating a single folder named Templates
. Each entry that lives inside Templates
represents an individual Template
.
After typing in the Name, click on Add New
as the content type and give it a personalised Name (here: Template
) as we'll be giving it our own blueprint. Click save to create an Templates
folder.
Click on Create New to start creating your first Template entry.
The current Template has an empty blueprint. Let's start defining our own schema by first adding a story.
Click on Define {1} to start defining the Template schema.
Add a Name field to the schema (type Text).
Similarly, add description
, publisher
,type
,css
,cms
and framework
fields to the schema as Text
type
Add demoUrl
& githubUrl
field to the schema as Link
type
Add overview
field to the schema as Markdown
type
After clicking and save filling the information, this is how it looks once filled in:
Next, obtain the preview API key (further referred to as STORYBLOK_API_KEY) shown in the tab Access Tokens of Settings. Obtain the token from the list as STORYBLOK_API_KEY.
Next, hit up the Visual Editor tab and set the Location (default environment) to https://localhost:3000
Set up SvelteKit 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:
After these steps, you should be able to start the local environment using the following command:
Create a file named .env
that’ll contain the STORYBLOK_API_KEY
as retrieved in the steps above, and shall look like the following:
With this done, let’s click on the window at the bottom left corner that brings up the Visual Editor and see the live preview.
Minifying HTML Output To Reduce Page Size in SvelteKit
To minify the HTML response generated via code in your pages, we use SvelteKit Hooks to check if the response is an HTML / page chunk and then use html-minifier
on the server to minify the response:
Generating Image Placeholders for Optimal UX in SvelteKit
Heavily inspired by Next.js Gallery, image(s) associated with their showcase template(s) are provided with blur images that show up as soon as the page loads, and waits for the complete image to load meanwhile. As we already know that the images are going to be not hosted with the app itself, we serve the images resized and compressed from Edgio’s Image Optimizer before generating an image’s base64 string version.
While Next.js offers a built-in support to blurDataURLs, in SvelteKit the same is achieved by adding some TailwindCSS classes (i.e. will-change-auto, transform-gpu, and transition) and referencing the blurDataURL from the function as above as the background-image of that img element.
Generating Loading Placeholders During Navigation For Instant Feedback in SvelteKit
The entry point of the app’s layout src/routes/+layout.svelte
is where you can conditionally figure out when to display the loading placeholders during navigation via the navigation module in SvelteKit stores. The following code figures out if user is navigating and satisfies some path based condition to which it’s navigating to, the user is displayed with a loading placeholder until data JSONs are entirely fetched from the server. This ensures that the user action of navigation is acknowledged, and is displayed with a similar skeleton to what’ll look when it’s done navigating.
Implementing Showcase Data Fetching and Revalidation
In this section, we'll be diving deep into how the data fetching and revalidation for the showcase gallery is done. We make constant use of Stale While Revalidate on the Edge to achieve 100% cache hit rates, and @storyblok/svelte
to fetch and display data on-demand.
Fetching Showcase Items on the Listing Page
The homepage (aka Listing Page) shows the filters and the items for the gallery. All of the items are fetched and filtered from (inside src/routes/+page.server.ts
), and then the HTML response is sent from the server to the client. To fetch up to 20 templates on the server side from Storyblok, the following code helps us get all the relevant showcase items. If no showcase items are found, a user is redirected to a 404 page.
After all the showcase items are collected, based on the keyName
and the search
query param, the list is filtered and then dispatched to the browser. As the filters can vary between multiple keys containing multiple values, the following code iterates over and filters accordingly:
Fetching Showcase Item on the Display Page
Showcase Item Page (aka Display Page) displays all the relevant information to that particular item in the gallery. All of the details are fetched (inside src/routes/templates/[slug]/+page.server.ts
), and then the HTML response is sent from the server to the client. In case no showcase item is found, a user is redirected to the home page. This all is done via the following code:
Stale While Revalidate on the Edge for Page(s) and Navigation JSON(s)
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 showcase pages (that start with /templates/
).
Inside the cache method, we prevent caching the page in the browser and enable only edge caching to always serve users fast and with the latest content, while allowing navigation JSONs to stay fresh in the browser for only 60 seconds. The edge option is set to maxAgeSeconds: 3600
to ensure that the data is cached for an hour and is revalidated thereafter. The staleWhileRevalidateSeconds
option is set to a year to allow the data to be served directly from the cache while the cache is being refreshed.
Also, with the custom cache key method, we can extend the cache to serve the same response until a new keyName
or search
query param is received in the URL. This allows to serve of different versions of the SSR’d pages directly from the cache instead of deferring into serverless for each request.
Creating OG Images With Satori and SvelteKit
Heavily inspired by Next.js OG Image at the Edge, the route src/routes/og/+server.ts
takes care of creating a templated OG Images for each showcase item page. The following GET endpoint of the og routes accepts text
, description
and image
URL query params to generate OG Images dynamically.
The above code converts Image
component to png and returns it directly from the server. The Image component is a Svelte Component which is gonna shape how that OG Image looks like when rendered in HTML. For example, the following creates two columns: 1. that displays the name and description of the template and 2. that displays the screenshot of the demoUrl of that showcase item:
That Image component then renders the props passed in the componentToPng function. Make sure that you’ve included a font in your server side bundle (this is handled in the github starter for you):
To avoid redundant requests that contain any of the required query params, we use EdgeJS to filter only the requests that contain required query params, and cache the requests if they don’t come with unique values of those params, via the following code in routes.cjs
:
An example of how the OG Card would appear on Facebook for the link:
Deploy from CLI
You can do a production build of your app and test it locally using:
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:
Go ahead! Publish more content on Storyblok, and browse the /templates/slug
route of your website to look for changes.
But does all this get me a great performance?
All the tech decisions behind the curation of this, i.e. Caching, Server Side Rendering, Loading Placeholders, Blur Image Placeholders, Minifying HTML, Brotli Compression, etc. etc. (more can be found inside the GitHub repo code), have led to great performance numbers! Have a look for yourself:
Performance: Test Configuration with SpeedVitals
Performance: Homepage aka Listing Page
OMG, for the whole world, the homepage is godly super fast! Report Link
Page: https://rishi-raj-jain-showcase-gallery-storyblok-svelte-5b8f53-default.edgio.link/
Performance: Showcase Item Page aka Display Page
Ma Ma Mia, the items pages too load super fast across the globe! Report Link
Summary
In this tutorial, we learned how to build our own Showcase Gallery with Storyblok CMS in a SvelteKit project and deploy it to Edgio.
Resource | Link |
---|---|
Github Example Repo | https://github.com/rishi-raj-jain/showcase-gallery-storyblok-sveltekit-edgio-starter/ |
SvelteKit Data Fetching | https://kit.svelte.dev/docs/load |
Edgio Caching | https://docs.edg.io/guides/v7/performance/caching |
Storyblok | https://www.storyblok.com/ |
Storyblok SDK for Svelte | https://github.com/storyblok/storyblok-svelte |
Storyblok in the Svelte Docs | https://www.storyblok.com/tc/sveltekit |
Storyblok APIs | https://www.storyblok.com/docs/api |