Chapter 7: Framework Integration

Haiyue
26min

Chapter 7: Framework Integration

Learning Objectives
  • Integrate Tailwind CSS in React projects
  • Use Tailwind CSS in Vue.js projects
  • Integration configuration with Next.js and Nuxt.js
  • Learn best practices in different build tools

React Project Integration

Create React App Integration

# Create React application
npx create-react-app my-tailwind-app
cd my-tailwind-app

# Install Tailwind CSS
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
/* src/index.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

Vite + React Integration

# Create Vite React application
npm create vite@latest my-tailwind-app -- --template react
cd my-tailwind-app
npm install

# Install Tailwind CSS
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  css: {
    postcss: './postcss.config.js',
  },
})

React Component Examples

// components/Button.jsx
import React from 'react'
import { cn } from '../utils/cn'

const Button = React.forwardRef(({
  className,
  variant = 'default',
  size = 'default',
  asChild = false,
  ...props
}, ref) => {
  const Comp = asChild ? "span" : "button"

  return (
    <Comp
      className={cn(
        "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
        {
          "bg-primary text-primary-foreground shadow hover:bg-primary/90": variant === 'default',
          "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90": variant === 'destructive',
          "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground": variant === 'outline',
          "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80": variant === 'secondary',
          "hover:bg-accent hover:text-accent-foreground": variant === 'ghost',
          "text-primary underline-offset-4 hover:underline": variant === 'link',
        },
        {
          "h-9 px-4 py-2": size === 'default',
          "h-8 rounded-md px-3 text-xs": size === 'sm',
          "h-10 rounded-md px-8": size === 'lg',
          "h-9 w-9": size === 'icon',
        },
        className
      )}
      ref={ref}
      {...props}
    />
  )
})

Button.displayName = "Button"

export { Button }
// components/Card.jsx
import React from 'react'
import { cn } from '../utils/cn'

const Card = React.forwardRef(({ className, ...props }, ref) => (
  <div
    ref={ref}
    className={cn(
      "rounded-xl border bg-card text-card-foreground shadow",
      className
    )}
    {...props}
  />
))
Card.displayName = "Card"

const CardHeader = React.forwardRef(({ className, ...props }, ref) => (
  <div
    ref={ref}
    className={cn("flex flex-col space-y-1.5 p-6", className)}
    {...props}
  />
))
CardHeader.displayName = "CardHeader"

const CardTitle = React.forwardRef(({ className, ...props }, ref) => (
  <h3
    ref={ref}
    className={cn("font-semibold leading-none tracking-tight", className)}
    {...props}
  />
))
CardTitle.displayName = "CardTitle"

const CardDescription = React.forwardRef(({ className, ...props }, ref) => (
  <p
    ref={ref}
    className={cn("text-sm text-muted-foreground", className)}
    {...props}
  />
))
CardDescription.displayName = "CardDescription"

const CardContent = React.forwardRef(({ className, ...props }, ref) => (
  <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
))
CardContent.displayName = "CardContent"

const CardFooter = React.forwardRef(({ className, ...props }, ref) => (
  <div
    ref={ref}
    className={cn("flex items-center p-6 pt-0", className)}
    {...props}
  />
))
CardFooter.displayName = "CardFooter"

export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
// App.jsx - Usage example
import React from 'react'
import { Button } from './components/Button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from './components/Card'

function App() {
  return (
    <div className="min-h-screen bg-gray-50 p-8">
      <div className="max-w-2xl mx-auto space-y-8">
        <h1 className="text-3xl font-bold text-center text-gray-900">
          React + Tailwind CSS
        </h1>

        {/* Button examples */}
        <div className="flex flex-wrap gap-4">
          <Button>Default Button</Button>
          <Button variant="outline">Outline Button</Button>
          <Button variant="destructive">Destructive Button</Button>
          <Button variant="ghost">Ghost Button</Button>
          <Button variant="link">Link Button</Button>
        </div>

        {/* Card example */}
        <Card>
          <CardHeader>
            <CardTitle>Project Title</CardTitle>
            <CardDescription>
              A React component example built with Tailwind CSS
            </CardDescription>
          </CardHeader>
          <CardContent>
            <p className="text-gray-600">
              Card content area displaying main information...
            </p>
          </CardContent>
        </Card>
      </div>
    </div>
  )
}

export default App

Utility Function

// utils/cn.js
import { clsx } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs) {
  return twMerge(clsx(inputs))
}

Vue.js Project Integration

Vue CLI Integration

# Create Vue application
vue create my-tailwind-app
cd my-tailwind-app

# Install Tailwind CSS
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Vite + Vue Integration

# Create Vite Vue application
npm create vue@latest my-tailwind-app
cd my-tailwind-app
npm install

# Install Tailwind CSS
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./index.html",
    "./src/**/*.{vue,js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Vue Component Examples

<!-- components/BaseButton.vue -->
<template>
  <button
    :class="buttonClasses"
    :disabled="disabled"
    @click="handleClick"
  >
    <slot />
  </button>
</template>

<script>
import { computed } from 'vue'

export default {
  name: 'BaseButton',
  props: {
    variant: {
      type: String,
      default: 'primary',
      validator: (value) => ['primary', 'secondary', 'outline', 'ghost'].includes(value)
    },
    size: {
      type: String,
      default: 'md',
      validator: (value) => ['sm', 'md', 'lg'].includes(value)
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },
  emits: ['click'],
  setup(props, { emit }) {
    const buttonClasses = computed(() => {
      const baseClasses = [
        'inline-flex',
        'items-center',
        'justify-center',
        'font-medium',
        'rounded-lg',
        'transition-all',
        'duration-200',
        'focus:outline-none',
        'focus:ring-2',
        'focus:ring-offset-2',
        'disabled:opacity-50',
        'disabled:cursor-not-allowed'
      ]

      // Variant styles
      const variantClasses = {
        primary: [
          'bg-blue-600',
          'text-white',
          'hover:bg-blue-700',
          'focus:ring-blue-500'
        ],
        secondary: [
          'bg-gray-200',
          'text-gray-900',
          'hover:bg-gray-300',
          'focus:ring-gray-500'
        ],
        outline: [
          'border',
          'border-gray-300',
          'text-gray-700',
          'bg-white',
          'hover:bg-gray-50',
          'focus:ring-blue-500'
        ],
        ghost: [
          'text-gray-700',
          'hover:bg-gray-100',
          'focus:ring-gray-500'
        ]
      }

      // Size styles
      const sizeClasses = {
        sm: ['px-3', 'py-1.5', 'text-sm'],
        md: ['px-4', 'py-2', 'text-base'],
        lg: ['px-6', 'py-3', 'text-lg']
      }

      return [
        ...baseClasses,
        ...variantClasses[props.variant],
        ...sizeClasses[props.size]
      ]
    })

    const handleClick = (event) => {
      if (!props.disabled) {
        emit('click', event)
      }
    }

    return {
      buttonClasses,
      handleClick
    }
  }
}
</script>
<!-- components/BaseCard.vue -->
<template>
  <div class="bg-white rounded-lg shadow-md border border-gray-200 overflow-hidden">
    <div v-if="$slots.header" class="px-6 py-4 border-b border-gray-200 bg-gray-50">
      <slot name="header" />
    </div>

    <div class="p-6">
      <slot />
    </div>

    <div v-if="$slots.footer" class="px-6 py-4 bg-gray-50 border-t border-gray-200">
      <slot name="footer" />
    </div>
  </div>
</template>

<script>
export default {
  name: 'BaseCard'
}
</script>
<!-- App.vue -->
<template>
  <div class="min-h-screen bg-gray-50 p-8">
    <div class="max-w-2xl mx-auto space-y-8">
      <h1 class="text-3xl font-bold text-center text-gray-900">
        Vue.js + Tailwind CSS
      </h1>

      <!-- Button examples -->
      <div class="flex flex-wrap gap-4">
        <BaseButton @click="handleClick">Default Button</BaseButton>
        <BaseButton variant="secondary" @click="handleClick">Secondary Button</BaseButton>
        <BaseButton variant="outline" @click="handleClick">Outline Button</BaseButton>
        <BaseButton variant="ghost" @click="handleClick">Ghost Button</BaseButton>
      </div>

      <!-- Card example -->
      <BaseCard>
        <template #header>
          <h3 class="text-lg font-semibold text-gray-900">Project Title</h3>
        </template>

        <p class="text-gray-600">
          A Vue.js component example built with Tailwind CSS.
        </p>

        <template #footer>
          <div class="flex justify-end space-x-3">
            <BaseButton variant="outline" size="sm">Cancel</BaseButton>
            <BaseButton size="sm">Confirm</BaseButton>
          </div>
        </template>
      </BaseCard>

      <!-- Form example -->
      <form @submit.prevent="handleSubmit" class="space-y-6">
        <div>
          <label class="block text-sm font-medium text-gray-700 mb-2">
            Email Address
          </label>
          <input
            v-model="form.email"
            type="email"
            class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
            placeholder="Enter email"
          >
        </div>

        <div>
          <label class="block text-sm font-medium text-gray-700 mb-2">
            Message
          </label>
          <textarea
            v-model="form.message"
            rows="4"
            class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
            placeholder="Enter message"
          ></textarea>
        </div>

        <BaseButton type="submit" class="w-full">
          Send Message
        </BaseButton>
      </form>
    </div>
  </div>
</template>

<script>
import { reactive } from 'vue'
import BaseButton from './components/BaseButton.vue'
import BaseCard from './components/BaseCard.vue'

export default {
  name: 'App',
  components: {
    BaseButton,
    BaseCard
  },
  setup() {
    const form = reactive({
      email: '',
      message: ''
    })

    const handleClick = () => {
      console.log('Button clicked')
    }

    const handleSubmit = () => {
      console.log('Form submitted', form)
    }

    return {
      form,
      handleClick,
      handleSubmit
    }
  }
}
</script>

Next.js Integration

Installation and Configuration

# Create Next.js application
npx create-next-app@latest my-tailwind-app
cd my-tailwind-app

# Next.js 13+ has built-in Tailwind CSS support
# If not, manually install
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',
    './app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
/* globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 222.2 84% 4.9%;
    --primary: 221.2 83.2% 53.3%;
    --primary-foreground: 210 40% 98%;
  }

  .dark {
    --background: 222.2 84% 4.9%;
    --foreground: 210 40% 98%;
    --primary: 217.2 91.2% 59.8%;
    --primary-foreground: 222.2 84% 4.9%;
  }
}

Next.js App Router Example

// app/layout.js
import './globals.css'

export const metadata = {
  title: 'Next.js + Tailwind CSS',
  description: 'A Next.js application built with Tailwind CSS',
}

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body className="min-h-screen bg-background font-sans antialiased">
        {children}
      </body>
    </html>
  )
}
// app/page.js
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'

export default function Home() {
  return (
    <main className="container mx-auto px-4 py-8">
      <div className="max-w-4xl mx-auto space-y-8">
        <div className="text-center space-y-4">
          <h1 className="text-4xl font-bold tracking-tight">
            Welcome to Next.js + Tailwind CSS
          </h1>
          <p className="text-xl text-muted-foreground">
            Build modern web applications
          </p>
        </div>

        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
          <Card>
            <CardHeader>
              <CardTitle>Quick Start</CardTitle>
              <CardDescription>
                Learn how to use Tailwind CSS in Next.js
              </CardDescription>
            </CardHeader>
            <CardContent>
              <p className="text-sm text-muted-foreground mb-4">
                Tailwind CSS provides rich utility classes...
              </p>
              <Button asChild>
                <Link href="/docs">View Docs</Link>
              </Button>
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle>Component Library</CardTitle>
              <CardDescription>
                Pre-built components for rapid development
              </CardDescription>
            </CardHeader>
            <CardContent>
              <p className="text-sm text-muted-foreground mb-4">
                Quickly build interfaces with our component library...
              </p>
              <Button variant="outline" asChild>
                <Link href="/components">Browse Components</Link>
              </Button>
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle>Example Projects</CardTitle>
              <CardDescription>
                Learn best practices and design patterns
              </CardDescription>
            </CardHeader>
            <CardContent>
              <p className="text-sm text-muted-foreground mb-4">
                View examples from real-world projects...
              </p>
              <Button variant="secondary" asChild>
                <Link href="/examples">View Examples</Link>
              </Button>
            </CardContent>
          </Card>
        </div>
      </div>
    </main>
  )
}

Next.js API Routes with Tailwind

// app/dashboard/page.js
import { Suspense } from 'react'

async function getData() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts')
  if (!res.ok) {
    throw new Error('Failed to fetch data')
  }
  return res.json()
}

function Loading() {
  return (
    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
      {[...Array(6)].map((_, i) => (
        <div key={i} className="animate-pulse">
          <div className="bg-gray-200 h-48 rounded-lg mb-4"></div>
          <div className="space-y-2">
            <div className="h-4 bg-gray-200 rounded w-3/4"></div>
            <div className="h-4 bg-gray-200 rounded w-1/2"></div>
          </div>
        </div>
      ))}
    </div>
  )
}

async function PostList() {
  const posts = await getData()

  return (
    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
      {posts.slice(0, 6).map((post) => (
        <Card key={post.id} className="hover:shadow-lg transition-shadow">
          <CardHeader>
            <CardTitle className="line-clamp-2">{post.title}</CardTitle>
          </CardHeader>
          <CardContent>
            <p className="text-muted-foreground line-clamp-3">
              {post.body}
            </p>
          </CardContent>
        </Card>
      ))}
    </div>
  )
}

export default function Dashboard() {
  return (
    <div className="container mx-auto px-4 py-8">
      <div className="space-y-8">
        <div>
          <h1 className="text-3xl font-bold tracking-tight">Dashboard</h1>
          <p className="text-muted-foreground">
            Manage your content and data
          </p>
        </div>

        <Suspense fallback={<Loading />}>
          <PostList />
        </Suspense>
      </div>
    </div>
  )
}

Nuxt.js Integration

Installation and Configuration

# Create Nuxt application
npx nuxi@latest init my-tailwind-app
cd my-tailwind-app
npm install

# Install Tailwind CSS module
npm install -D @nuxtjs/tailwindcss
// nuxt.config.ts
export default defineNuxtConfig({
  devtools: { enabled: true },
  modules: [
    '@nuxtjs/tailwindcss'
  ],
  tailwindcss: {
    exposeConfig: true,
    viewer: true,
  }
})

Nuxt Component Examples

<!-- components/AppHeader.vue -->
<template>
  <header class="bg-white shadow-sm border-b">
    <nav class="container mx-auto px-4">
      <div class="flex items-center justify-between h-16">
        <NuxtLink to="/" class="text-xl font-bold text-gray-900">
          My App
        </NuxtLink>

        <div class="hidden md:flex items-center space-x-6">
          <NuxtLink
            to="/"
            class="text-gray-600 hover:text-gray-900 transition-colors"
            active-class="text-blue-600 font-medium"
          >
            Home
          </NuxtLink>
          <NuxtLink
            to="/about"
            class="text-gray-600 hover:text-gray-900 transition-colors"
            active-class="text-blue-600 font-medium"
          >
            About
          </NuxtLink>
          <NuxtLink
            to="/contact"
            class="text-gray-600 hover:text-gray-900 transition-colors"
            active-class="text-blue-600 font-medium"
          >
            Contact
          </NuxtLink>
        </div>

        <button class="md:hidden p-2 text-gray-600">
          <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
          </svg>
        </button>
      </div>
    </nav>
  </header>
</template>
<!-- pages/index.vue -->
<template>
  <div>
    <AppHeader />

    <main class="container mx-auto px-4 py-8">
      <section class="text-center space-y-8 py-20">
        <h1 class="text-5xl font-bold text-gray-900">
          Welcome to
          <span class="bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
            Nuxt.js
          </span>
        </h1>

        <p class="text-xl text-gray-600 max-w-2xl mx-auto">
          Build beautiful, responsive user interfaces with Tailwind CSS
        </p>

        <div class="flex flex-col sm:flex-row gap-4 justify-center">
          <NuxtLink
            to="/docs"
            class="inline-flex items-center px-6 py-3 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 transition-colors"
          >
            Get Started
          </NuxtLink>
          <NuxtLink
            to="/examples"
            class="inline-flex items-center px-6 py-3 border border-gray-300 text-gray-700 font-medium rounded-lg hover:bg-gray-50 transition-colors"
          >
            View Examples
          </NuxtLink>
        </div>
      </section>

      <section class="py-20">
        <div class="text-center mb-16">
          <h2 class="text-3xl font-bold text-gray-900 mb-4">Features</h2>
          <p class="text-lg text-gray-600">Explore our core functionality</p>
        </div>

        <div class="grid grid-cols-1 md:grid-cols-3 gap-8">
          <div class="text-center p-6">
            <div class="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center mx-auto mb-4">
              <svg class="w-6 h-6 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
              </svg>
            </div>
            <h3 class="text-xl font-semibold text-gray-900 mb-2">Rapid Development</h3>
            <p class="text-gray-600">Quickly build user interfaces with utility classes</p>
          </div>

          <div class="text-center p-6">
            <div class="w-12 h-12 bg-green-100 rounded-lg flex items-center justify-center mx-auto mb-4">
              <svg class="w-6 h-6 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"/>
              </svg>
            </div>
            <h3 class="text-xl font-semibold text-gray-900 mb-2">Responsive Design</h3>
            <p class="text-gray-600">Built-in responsive utility classes</p>
          </div>

          <div class="text-center p-6">
            <div class="w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center mx-auto mb-4">
              <svg class="w-6 h-6 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h4a2 2 0 012-2v-1a2 2 0 00-2-2H7m-2-4h2m8 2v2"/>
              </svg>
            </div>
            <h3 class="text-xl font-semibold text-gray-900 mb-2">Highly Customizable</h3>
            <p class="text-gray-600">Fully customizable design system</p>
          </div>
        </div>
      </section>
    </main>
  </div>
</template>

Build Tool Best Practices

PostCSS Configuration Optimization

// postcss.config.js
module.exports = {
  plugins: {
    'tailwindcss': {},
    'autoprefixer': {},
    ...(process.env.NODE_ENV === 'production'
      ? {
          'cssnano': {
            preset: ['default', {
              discardComments: { removeAll: true },
            }]
          }
        }
      : {}
    )
  }
}

Webpack Configuration Optimization

// webpack.config.js
const path = require('path')

module.exports = {
  // Other configuration...
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@components': path.resolve(__dirname, 'src/components'),
      '@utils': path.resolve(__dirname, 'src/utils'),
    }
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
          'postcss-loader'
        ]
      }
    ]
  }
}

Vite Configuration Optimization

// vite.config.js
import { defineConfig } from 'vite'
import path from 'path'

export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@components': path.resolve(__dirname, './src/components'),
      '@utils': path.resolve(__dirname, './src/utils'),
    }
  },
  css: {
    postcss: './postcss.config.js',
    devSourcemap: true
  },
  build: {
    cssCodeSplit: true,
    rollupOptions: {
      output: {
        assetFileNames: (assetInfo) => {
          if (assetInfo.name === 'style.css') return 'assets/main.[hash].css'
          return 'assets/[name].[hash].[ext]'
        }
      }
    }
  }
})

Summary

Through this chapter, you should have mastered:

  • React Integration: Configuring and using Tailwind CSS in different React projects
  • Vue.js Integration: Best practices for Tailwind CSS in Vue projects
  • Next.js Integration: Optimizing Tailwind CSS usage with Next.js features
  • Nuxt.js Integration: Seamlessly integrating Tailwind CSS in Nuxt projects
  • Build Optimization: Configuration and optimization strategies for different build tools

These skills enable you to efficiently use Tailwind CSS in any modern frontend framework.