Uniform how-to/Build a Component Library with Tailwind UI and Nuxt 3

Build a Component Library with Tailwind UI and Nuxt 3

Components in apps are building blocks that perform related functions that are pluggable and reusable. Popular frameworks have all adopted the component way as an effective approach.
TailwindUI is a collection of well-designed components and templates ideal for building websites and apps. 
This tutorial, whose source code is on GitHub, describes how to create a component library with TailwindUI and Uniform in Nuxt 3 in the StackBlitz IDE, which you can leverage with this codeline:
<iframe src="https://stackblitz.com/edit/github-anehxu?embed=1&file=app.vue"></iframe>Click to copy

Understanding the prerequisites

To fully grasp the concepts in this tutorial, you must have—
  • A basic understanding of Vue and Nuxt
  • A fundamental knowledge of Tailwind CSS
  • A Uniform account, which you can create for free.
Uniform offers digital experience composition (DXC) features with which you can create, deliver, and manage building blocks for apps. Instead of making multiple API requests, you can employ Jamstack technologies, such as headless content-management systems, commerce APIs, and CDNs, and deliver digital experiences as a single source of truth.

Getting started

First, create a Nuxt 3 starter project by typing this command in a directory of your choice:
1npx nuxi init uniform-nuxt && cd uniform-nux
In the project directory, install the project dependencies: npm i Click to copy

Adding TailwindCSS support

Next, install and configure TailwindCSS, a prerequisite for TailwindUI, in your app. Follow these steps:
  1. Install Tailwind CSS and its dependencies. Type
    1npm install -D tailwindcss postcss@latest autoprefixer@latest @nuxt/postcss8
    2npx tailwindcss init
    The above command line also creates a tailwind.config.jsClick to copy file for configuring Tailwind CSS.
  2. Add the paths to the template files to the tailwind.config.jsClick to copy file, like this:
    1 /** @type {import('tailwindcss').Config} */
    2module.exports = {
    3  content: [
    4    './components/**/*.{js,vue,ts}',
    5    './layouts/**/*.vue',
    6    './pages/**/*.vue',
    7    './**/*.vue',
    8    './plugins/**/*.{js,ts}',
    9  ],
    10  theme: {
    11    extend: {},
    12  },
    13  plugins: [],
    14};
  3. Create an assets/css/tailwind.cssClick to copy file in the root directory and add Tailwind CSS directives:
    1@tailwind base;
    2@tailwind components;
    3@tailwind utilities;
  4. Add the Tailwind CSS dependencies and the newly created style to configure Nuxt 3 by updating the nuxt.config.jsClick to copy file with the code below: import { defineNuxtConfig } from 'nuxt';Click to copy
    1// https://v3.nuxtjs.org/api/configuration/nuxt.config
    2export default defineNuxtConfig({
    3  build: {
    4    postcss: {
    5      postcssOptions: {
    6        plugins: {
    7          tailwindcss: {},
    8          autoprefixer: {},
    9        },
    10      },
    11    },
    12  },
    13  css: ['~/assets/css/tailwind.css']
    14});

Adding TailwindUI

Now add Tailwind UI to your app:
  1. Install the required dependencies: npm install @headlessui/vue @heroicons/vueClick to copy
  2. Update the app.vue Click to copyfile with this code:
    1<!-- This example requires Tailwind CSS v2.0+ -->
    2<template>
    3  <div class="py-12 bg-white">
    4    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
    5      <div class="lg:text-center">
    6        <h2 class="text-base text-indigo-600 font-semibold tracking-wide uppercase">Transactions</h2>
    7        <p class="mt-2 text-3xl leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl">A better way to send money</p>
    8        <p class="mt-4 max-w-2xl text-xl text-gray-500 lg:mx-auto">Lorem ipsum dolor sit amet consect adipisicing elit. Possimus magnam voluptatum cupiditate veritatis in accusamus quisquam.</p>
    9      </div>
    10      <div class="mt-10">
    11        <dl class="space-y-10 md:space-y-0 md:grid md:grid-cols-2 md:gap-x-8 md:gap-y-10">
    12          <div v-for="feature in features" :key="feature.name" class="relative">
    13            <dt>
    14              <div class="absolute flex items-center justify-center h-12 w-12 rounded-md bg-indigo-500 text-white">
    15                <component :is="feature.icon" class="h-6 w-6" aria-hidden="true" />
    16              </div>
    17              <p class="ml-16 text-lg leading-6 font-medium text-gray-900">{{ feature.name }}</p>
    18            </dt>
    19            <dd class="mt-2 ml-16 text-base text-gray-500">
    20              {{ feature.description }}
    21            </dd>
    22          </div>
    23        </dl>
    24      </div>
    25    </div>
    26  </div>
    27</template>
    28<script setup>
    29import { AnnotationIcon, GlobeAltIcon, LightningBoltIcon, ScaleIcon } from '@heroicons/vue/outline'
    30const features = [
    31  {
    32    name: 'Competitive exchange rates',
    33    description:
    34      'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.',
    35    icon: GlobeAltIcon,
    36  },
    37  {
    38    name: 'No hidden fees',
    39    description:
    40      'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.',
    41    icon: ScaleIcon,
    42  },
    43  {
    44    name: 'Transfers are instant',
    45    description:
    46      'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.',
    47    icon: LightningBoltIcon,
    48  },
    49  {
    50    name: 'Mobile notifications',
    51    description:
    52      'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.',
    53    icon: AnnotationIcon,
    54  },
    55]
    56</script
Note: Tailwind UI comes with free and paid templates. The template in this tutorial is a free marketing template.
  1. Finally, start a development server:
    1npm run dev

Putting it all together on Uniform

Now create a component library on Uniform.
  1. Log in to your Uniform account and click Create New Project at the top. Type marketing_featureClick to copy under Give your project a name and click Continue.
  2. Click the Security tab at the top, then API Keys, and then the + icon to create an API key. Input marketing_featureClick to copy as the API name, click Add to Project, select all the permissions, and click Set Permissions. Finally, click Create API Key.
A screen that contains your API Key and Project ID is then displayed.
Before closing the screen, create a .envClick to copy file in your app’s root directory and add this code snippet to the file:
1NUXT_ENV_API_KEY=/REPLACE WITH API KEY/
2NUXT_ENV_PROJECT_ID=/REPLACE WITH PROJECT ID/
Click to copy

Understanding and setting up components and compositions on Uniform

Components in Uniform apps work similarly to those in Vue apps, i.e., you can break up an app into smaller, reusable building blocks with properties. A composition contains one or more components. 
For this project, create a single header_componentClick to copy and four instances of body_componentClick to copy.
Follow these steps:
1. Click the Projects tab at the top and then the project. Afterwards, click the Canvas tab at the top, then Component Library, and the + icon.
Parameter Name
Help Text
Type
Required?
mini title
Mini title
Text
Yes
main title
Main title
Text
Yes
description
Description
Text
Yes
2. Type header_componentClick to copy as the component name, add the properties of mini titleClick to copy, main titleClick to copy, and descriptionClick to copy as shown above, and then click OK.
3. Click Save and Close.
Similarly, create a body_componentClick to copy component with these properties:
Parameter Name
Help Text
Type
Required?
title
Title
Text
Yes
description
Description
Text
Yes
Be sure to click Save and Close.
header_componentClick to copy and body_componentClick to copy now serve as the blueprints or building blocks for your marketing landing page. Create that page with the following steps:
  1. Click the + icon, type PageClick to copy under Component Name, and select Composition Component. Afterwards, click Slots below and click the + icon to create a slot.
    Note: With slots, you can create component instances (a total of five in this tutorial), which can accept data dynamically.
  2. Type ItemsClick to copy under Slot Name, 0Click to copy under Minimum, 5Click to copy under Maximum (the header section and the four body sections), and select body_componentClick to copy and header_componentClick to copy under Allowed Components. Click OK.
  3. Finally, click Save and Close.
You can now build your marketing landing page with the PagesClick to copy component. Do the following:
  1. Click Compositions on the left and then the + icon to create a composition.
  2. Select PageClick to copy as the composition type, input HomepageClick to copy as the name, and click Create.
  3. Type itemsClick to copy under Slug and click the + icon to add a component to map out a new component.
    Note: The slug you added will come in handy for composition searches.
  4. Select header_componentClick to copy and add the corresponding text under mini titleClick to copy, main titleClick to copy, and descriptionClick to copy as hard-coded in your Nuxt 3 app.
  5. Repeat the above steps to add the remaining body_componentClick to copy data and then click Save and Publish.
  6. Navigate back to the Canvas tab and click Publish to make your composition available to third-party apps.

Integrating Uniform with Nuxt 3

To integrate Uniform with Nuxt 3:
  1. Install the required dependencies with this command: npm install @uniformdev/canvas @uniformdev/context @uniformdev/canvas-vue @uniformdev/context-vue @uniformdev/uniform-nuxtClick to copy
  2. Configure and register Uniform as a module in your Nuxt 3 app by editing the nuxt.config.tsClick to copy file to read as follows: import { defineNuxtConfig } from 'nuxt';Click to copy
    1// https://v3.nuxtjs.org/api/configuration/nuxt.config
    2export default defineNuxtConfig({
    3  build: {
    4    postcss: {
    5      postcssOptions: {
    6        plugins: {
    7          tailwindcss: {},
    8          autoprefixer: {},
    9        },
    10      },
    11    },
    12  },
    13  css: ['~/assets/css/tailwind.css'],
    14  //add below section
    15  modules: ['@uniformdev/uniform-nuxt'],
    16  uniform: {
    17    projectId: process.env.NUXT_ENV_PROJECT_ID,
    18    readOnlyApiKey: process.env.NUXT_ENV_API_KEY,
    19  },
    20});
  3. Retrieve your data with an API call through the configured Uniform module by editing the app.vueClick to copy file to read like this:
    1<!-- This example requires Tailwind CSS v2.0+ -->
    2<template>
    3  <Composition v-if="composition" :data="composition">
    4    <div class="py-12 bg-white">
    5      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
    6        <div class="lg:text-center">
    7          <h2
    8            class="text-base text-indigo-600 font-semibold tracking-wide uppercase"
    9          >{{composition.slots.items[0].parameters.miniTitle.value}}</h2>
    10          <p
    11            class="mt-2 text-3xl leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl"
    12          >{{composition.slots.items[0].parameters.mainTitle.value}}</p>
    13          <p
    14            class="mt-4 max-w-2xl text-xl text-gray-500 lg:mx-auto"
    15          >{{composition.slots.items[0].parameters.description.value}}</p>
    16        </div>
    17        <div class="mt-10">
    18          <dl class="space-y-10 md:space-y-0 md:grid md:grid-cols-2 md:gap-x-8 md:gap-y-10">
    19            <div
    20              v-for="(feature, i) in composition.slots.items.slice(1)"
    21              :key="feature.name"
    22              class="relative"
    23            >
    24              <dt>
    25                <div
    26                  class="absolute flex items-center justify-center h-12 w-12 rounded-md bg-indigo-500 text-white"
    27                >
    28                  <component :is="iconArray[i]" class="h-6 w-6" aria-hidden="true" />
    29                </div>
    30                <p
    31                  class="ml-16 text-lg leading-6 font-medium text-gray-900"
    32                >{{ feature.parameters.title.value }}</p>
    33              </dt>
    34              <dd
    35                class="mt-2 ml-16 text-base text-gray-500"
    36              >{{ feature.parameters.description.value }}</dd>
    37            </div>
    38          </dl>
    39        </div>
    40      </div>
    41    </div>
    42  </Composition>
    43</template>
    44<script setup>
    45import {
    46  AnnotationIcon,
    47  GlobeAltIcon,
    48  LightningBoltIcon,
    49  ScaleIcon
    50} from "@heroicons/vue/outline";
    51const iconArray = [AnnotationIcon, GlobeAltIcon, LightningBoltIcon, ScaleIcon];
    52const { $useComposition } = useNuxtApp();
    53const { data: compositionData } = await $useComposition({ slug: "items" });
    54const composition = computed(() => compositionData.value.composition);
    55</script>
The snippet above does the following:
  1. Creates an iconArrayClick to copy array to store the icons.
  2. Retrieves data from Uniform with the $useCompositionClick to copy instance by passing on the itemsClick to copy slug you configured on Uniform earlier.
  3. Creates a compositionClick to copy variable to hold the composition retrieved from Uniform.
  4. Performs a conditional check: If compositionClick to copy is not empty, dynamically update the UI with the compositionClick to copy component.
Now you can restart your development server. Type: npm run devClick to copy

Configuring Live Previews

Uniform’s intuitive UI enables developers to preview changes in realtime and avoid context switching between the platform and the codebase. To set up live previews:
  1. Click the Settings tab followed by Canvas, and then input the development URL http://localhost:3000/?preview=trueClick to copy. Click Save.
    Note: For deployed apps, be sure to input the correct URL. For example, input https://myapp.com/?preview=trueClick to copy for the app https://myapp.comClick to copy.
  2. Navigate back to the Canvas tab and click Homepage composition. The Preview button is displayed on the top-right corner.
    To test the live-preview capability and see changes in real time, edit a component, save it, and click Preview.

Exploring other resources

You’ve now learned how to create a component library with TailwindUI and Uniform in Nuxt 3. Besides enhancing the digital experience and raisingapp performance with only a single API call, Uniform also shortens time tomarket by offering developers and nondevelopers a seamless and intuitive UI for content edits.
Here are a few helpful resources: