Nuxt, Medusa, TailwindCSS Crash Course
Tags: vue, javascript, tailwindcss, webdev
Published: 2023-02-27 09:03:42

I really enjoyed building apps with Nuxt. It is currently my favourite web framework with tons of modules, plugins, and configuration options.

In this article, I will be showing you how you can build a simple Product Gallery (and in the future, powerful Headless Commerce website) with Nuxt, [Tailwind](https://tailwindcss.com/), and [Medusa](https://medusajs.com/).

This article will also showcase a Nuxt Module that I have recently created -> https://github.com/baroshem/nuxt-medusa. Make sure to star it on🚀 GitHub as it motivates me to make the module even better! 

In the upcoming weeks I will also record a video tutorial on my YouTube channel about the same topic.

All the code from this tutorial is available in following GitHub repository:

https://github.com/Baroshem/nuxt-tailwind-medusa

## Technology Stack

Before we jump into an actual code, let's talk briefly about our technology stack.

For the connection to Medusa, we will be using an module that I have recently created called `nuxt-medusa` :

![Nuxt Medusa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dhcxhzlv7tmvaa5d4ekm.png)

For styling, I will be also using an official Nuxt Tailwind module:

![Nuxt Tailwind](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qqh7z6qd829yzoeixlux.png)

And for image optimization, the official Nuxt module as well:

![Nuxt Image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ol3cjflxj5eri4arkr3f.png)

Let's now go to the code to see how we can build our application with previously mentioned technologies:

## Code

I have generated a simple Nuxt project using following command:

```bash
npx nuxi init <project-name>
```

Then, I have opened the project in my IDE and installed all the dependencies by using this command:

```bash
yarn install
```

To see if it works correctly, let's just run the application with following command:

```bash
yarn dev
```

If installation and build was successful, we should see a nice looking Nuxt Hello World page once we visit `http://localhost:3000`.

Now, let's install all required modules (Medusa, Tailwind, Image):

```bash
yarn add --dev @nuxt/image-edge @nuxtjs/tailwindcss nuxt-medusa
```

And next, let's add them to `modules` section in `nuxt.config.ts` file:

```ts
export default defineNuxtConfig({
    modules: ['nuxt-medusa', '@nuxtjs/tailwindcss', '@nuxt/image-edge'],
})
```

In order to have optimized images, you should add following image configuration object as instructed [here](https://v1.image.nuxtjs.org/configuration#domains):

```ts
export default defineNuxtConfig({
    ...
    image: {
        domains: ['medusa-public-images.s3.eu-west-1.amazonaws.com']
    }
})
```

If you do not have a Medusajs project yet, you can generate one by running following command:

```bash
npx create-medusa-app
```

Medusa will have a CORS setting for a storefront by default set to `http://localhost:8000` in the `medusa-config.js` file so let's change it to `http://localhost:3000` (default nuxt app port).

```ts
// CORS to avoid issues when consuming Medusa from a client
const STORE_CORS = process.env.STORE_CORS || "http://localhost:3000";
```

Also, don't forget about `.env` file for Medusa (which is by default running on port 9000):

```bash
MEDUSA_URL=http://localhost:9000
```

Now, let's add the following code to the `app.vue` global component (I will explain each section below):

```vue
<script lang="ts" setup>
const client = useMedusaClient();
const { products } = await client.products.list();
</script>

<template>
  <div class="flex">
    <div v-for="product in products" class="mx-2">
      <div class="relative rounded-lg shadow-lg">
        <NuxtImg
          :src="product.thumbnail"
          class="shadow-lg rounded-lg opacity-1 hover:opacity-75 transition duration-300 ease-in-out w-full"
          format="webp"
        />
        <div class="p-6">
          <h5 class="font-bold text-lg mb-3">{{ product.title }}</h5>
          <pre class="text-gray-500 mb-4">{{
            product.variants[0].prices[0].amount
          }}</pre>
          <p>{{ product.description }}</p>
        </div>
      </div>
    </div>
  </div>
</template>
```

1. In the `script` section we are calling a `useMedusaClient` composable to have access to the Medusa client.
2. We are using this client to fetch the product list and destructure `products` from it.
3. In the `template` section we are using these `products` to generate multiple product cards by utilizing a `v-if`. We are also applying some Tailwind classes to make the elements look much nicer. We are also using the `NuxtImg` component with attribute `format` set to `webp`. This ensures that our images will have lighter `webp` format and will be fetched faster.

If we did everything correctly, we should see the following result once we visit `http://localhost:3000`:

![Nuxt, Medusa, Tailwind](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x1ic281fi1vbdn1rp0uo.png)

## Summary

And that's it! You have just built a simple Product Gallery with Nuxt, Tailwind, and Medusa! Don' forget to star the project on GitHub https://github.com/baroshem/nuxt-medusa :)