DEV Community

Cover image for Building a Nuxt Modules clone with Nuxt 3, TailwindCSS, Storyblok, and Vercel
Jakub Andrzejewski
Jakub Andrzejewski

Posted on

Building a Nuxt Modules clone with Nuxt 3, TailwindCSS, Storyblok, and Vercel

The Release Candidate version of Nuxt 3 dropped out of nowhere! The official release was rescheduled few times but we finally have it so it would be awesome to dive deeper into what it brings to the Nuxt ecosystem. And this is exactly what me and @alvarosabu did during our most recent video colaboration that I highly recommend you to check out with a link below:

In this article, I will summarize each step that we have taken in the video with a written examples and step by step guide. Enjoy!

If you get lost at some point, you can always check out the following github repository:

https://github.com/alvarosabu/nuxt-modules-clone

Nuxt 3

The first step is to generate new project using:

npx nuxi init nuxt-modules-clone
Enter fullscreen mode Exit fullscreen mode

This will generate a default Nuxt 3 project. Let's try to test the newest addition to the ecosystem which is the support for Static Site Generation. In nuxt.config.ts add following line:

export default defineNuxtConfig({
    ssr: false,  // <-
})
Enter fullscreen mode Exit fullscreen mode

Now, let's build the project with the following command:

yarn generate
Enter fullscreen mode Exit fullscreen mode

Finally, if we serve the generated static HTML files with the following command:

serve .output/public
Enter fullscreen mode Exit fullscreen mode

*serve is an addition to VS Code that allows to serve static files with local server

We should now see the same result as with yarn dev in the broweser. Awesome!

TailwindCSS

We now how to generate a static HTML page. Now, let's add a bit of styling into it to make it look a bit better. We will install TailwindCSS by using the official Nuxt module and style some parts of the application.

The installation of the module is relatively simple. Just use the following command:

yarn add --dev @nuxtjs/tailwindcss
Enter fullscreen mode Exit fullscreen mode

And register the module in nuxt.config.ts in the modules array:

export default defineNuxtConfig({
    modules: ['@nuxtjs/tailwindcss'] // <-
})
Enter fullscreen mode Exit fullscreen mode

From now on, you can use the TailwindCSS across your application. We will create a TheHeader.vue component by using the official Nuxt 3 CLI method:

npx nuxi add component TheHeader
Enter fullscreen mode Exit fullscreen mode

And add a bit of styling into it:

<script lang="ts" setup></script>

<template>
  <header class="bg-white py-4 shadow-lg">
    <div class="container mx-auto">
      <a href="" class="flex items-center"> <img class="h-8 w-8 mr-4" src="/logo.svg" /> Nuxt Module</a>
    </div>
  </header>
</template>

<style scoped></style>
Enter fullscreen mode Exit fullscreen mode

Inside /public/logo.svg add following svg code:

<svg width="40" height="40" viewBox="0 0 70 70" fill="none" xmlns="http://www.w3.org/2000/svg" alt="Nuxt"><path d="M31.4918 17.1505C29.8172 14.2712 25.6308 14.2712 23.9562 17.1505L5.70589 48.5305C4.03131 51.4099 6.12453 55.009 9.4737 55.009H23.7209C22.2898 53.7583 21.7598 51.5946 22.8428 49.7382L36.6648 26.0451L31.4918 17.1505Z" fill="#80EEC0"></path><path d="M43.0556 24.0338C44.4415 21.678 47.9061 21.678 49.292 24.0338L64.3957 49.7083C65.7816 52.0641 64.0493 55.0089 61.2775 55.0089H31.0701C28.2984 55.0089 26.566 52.0641 27.9519 49.7083L43.0556 24.0338Z" fill="#00DC82"></path></svg>
Enter fullscreen mode Exit fullscreen mode

Finally, we can use our new TheHeader component inside our app.vue

<template>
  <TheHeader />
</template>
Enter fullscreen mode Exit fullscreen mode

Storyblok

To add content into our page we will use Storyblok CMS.

Let's install the required dependencies by typing following command:

yarn add @storyblok/vue
yarn add --dev axios
Enter fullscreen mode Exit fullscreen mode

In order to make Storyblok work, we will use a Nuxt plugin. Create /plugins/storyblok.ts file and add following code into it:

import {
    StoryblokVue, apiPlugin
} from '@storyblok/vue';

export default defineNuxtPlugin(nuxtApp => {
    const config = useRuntimeConfig().public

    nuxtApp.vueApp.use(StoryblokVue, {
        accessToken: config.apiToken,
        use: [apiPlugin]
    });
})
Enter fullscreen mode Exit fullscreen mode

*Remember to create a .env file with an access token grabbed from Storyblok.

Let's add storyblok token to runtimeConfig:

export default defineNuxtConfig({
    runtimeConfig: {
        public: {
            apiToken: process.env.STORYBLOK_TOKEN
        }
    },
})
Enter fullscreen mode Exit fullscreen mode

Now, let's create a ModuleCard component that we will use to show each module:

<script lang="ts" setup>
const props = defineProps({
  name: {
    type: String,
    default: "Module Card"
  },
  description: {
    type: String,
    default: "Crazy description"
  },
  icon: {
    type: Object,
    default: () => ({})
  },
  url: {
    type: Object,
    default: () => ({})
  }
})
</script>

<template>
  <a class="flex justify-center" :href="url.url">
    <div class="flex items-center p-8 flex-col md:flex-row md:max-w-xl rounded-lg bg-white shadow-lg">
      <img class="w-10 h-10 object-fit" :src="icon.filename" :alt="icon.alt" />
      <div class="px-8 flex flex-col justify-start">
        <h5 class="text-gray-900 text-xl font-medium mb-2">{{name}}</h5>
        <p class="text-gray-700 text-base mb-4">
          {{description}}
        </p>
      </div>
    </div>
  </a>
</template>

<style scoped></style>
Enter fullscreen mode Exit fullscreen mode

Finally, let's use all before created parts in our app.vue root page:

<script setup lang="ts">
 import { useStoryblokApi } from "@storyblok/vue";
  const storyblokApi = useStoryblokApi();
  const { data } = await storyblokApi.get("cdn/stories", { version: "draft", starts_with: 'modules' });
  const modules = computed(() => data.stories);
</script>

<template>
  <TheHeader />
  <div class="container mx-auto p-8 grid grid-cols-1 md:grid-cols-3 gap-4">
    <ModuleCard v-for="module in modules" v-bind="module.content" />
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Vercel

The whole configuration of Vercel is well defined in the video so I will just summarize it.

Import github repository in Vercel

Vercel Dashboard

Define proper build command:

Vercel settings

Build command should be yarn generate and output folder .output/public

Finally, add Storyblok token as Environment Variable:

Vercel Environment Variables

If all went well with the configuration, you should see similar result as our demo https://nuxt-modules-clone.vercel.app/

Demo

Summary

Well done! You have just created a simple Nuxt Modules clone with Nuxt 3 SSG, TailwindCSS, Storyblok, and Vercel. We covered a lot in this article so take a little brake and then get back to the topic as there is much more to discover!

Bonus

Below, I am posting some links that might be useful for you:

Discussion (0)