Let's go back to the initial topic which is finding what is in my opinion the dream stack for building Jamstack applications.
If you are interested in more visual explanation of this article, I gave a talk about this topic that you can check out below:
[γγ¬γΌγ ]
Jamstack
Jamstack is an architectural approach that decouples the web experience layer from data and business logic, improving flexibility, scalability, performance, and maintainability.
Jamstack Architecture
You can check more about this concept here -> https://jamstack.org/
In our case, we will be using following technologies for JavaScript, API, and Markup
Jamstack, Nuxt, Storyblok
Our JAM
We will be using Nuxt 3 as our main framework, NuxtContent (to be able to write Markdown), a little bit of TailwindCSS styling, and Storyblok which will be our API. Finally, we will be deploying our app to Vercel.
You can check out all those tools and technologies below:
Code
Below, I have added some of the code snippets that I have found the most important for this tutorial. The full code can be seen here -> https://github.com/Baroshem/jamstack-storyblok-nuxt and also in the video linked at the top.
We will be using below Vue.js component to display an image of the cat. It will be used later for both static local data and dynamic data fetched from Storyblok:
// components/content/CatImage.vue
<template>
<div class="flex flex-wrap w-1/3">
<p>{{ title }}</p>
<div class="w-full p-1 md:p-2 relative">
<img
class="block object-cover object-center w-full h-full rounded-lg"
:alt="title"
:src="src"
>
</div>
</div>
</template>
<script setup lang="ts">
const props = defineProps({
src: {
type: String,
required: true,
},
title: {
type: String,
required: true,
}
})
</script>
This component accepts two props (src and title) that are used for each individual image of the cat.
Apart from that, we have also created a gallery component that is used to display an array of cats fetched from Storyblok.
// components/content/CatImageGallery.vue
<template>
<section class="overflow-hidden text-gray-700 ">
<div class="container px-5 py-2 mx-auto lg:pt-12 lg:px-32">
<div class="flex flex-wrap -m-1 md:-m-2">
<cat-image
v-for="image in story.content.body"
:key="image.id"
:title="image.title"
:src="image.src.filename"
/>
</div>
</div>
</section>
</template>
<script setup lang="ts">
const story = await useAsyncStoryblok("home", { version: "draft" });
</script>
The most important file for us is the index.md file where we are creating our content that consists of normal .md content, vue.js components with local data, and an array of cat images built with the data fetched from Storyblok.
// content/index.md
# Testing Nuxt Content
*Hello from Nuxt Content*
:cat-image{src=https://a.storyblok.com/f/126375/600x644/497572edee/cat-dog.jpeg title="My Favorite Cat from Markdown"}
:cat-image{src=https://a.storyblok.com/f/126375/600x644/497572edee/cat-dog.jpeg title="Second Favorite Cat"}
:cat-image-gallery
Thanks to this, we are now able to connect three JAM elements (JS, API, Markup) with usage of Vue.js components, .md content, and data from Storyblok.
In order to see the actual result, we need to add following component to our main app.vue page.
// app.vue
<template>
<div>
<ContentDoc path="/" class="prose text-left" />
</div>
</template>
Also, also. Don't forget to add following configuration to nuxt.config.ts. Without it none of this will work ;)
// nuxt.config.ts
// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
modules: [
'@nuxt/content',
'@nuxtjs/tailwindcss',
["@storyblok/nuxt", { accessToken: process.env.STORYBLOK_ACCESS_TOKEN }]
],
})
Summary
Well done! By following this simple tutorial, you have managed to create a Cat Image Gallery application that is powered by static .md content, vue.js local data, and dynamic data fetched from Storyblok. Let me know if you would like me to dive deeper into JAMstack ecosystem and I will totally do it!