🎯

vue-best-practices

🎯Skill

from dedalus-erp-pas/foundation-skills

VibeIndex|
What it does

Provides comprehensive Vue.js 3 best practices guidelines for writing idiomatic, maintainable code using Composition API, Tailwind CSS, and PrimeVue.

πŸ“¦

Part of

dedalus-erp-pas/foundation-skills(21 items)

vue-best-practices

Installation

Quick InstallInstall with npx
npx add-skill Dedalus-ERP-PAS/foundation-skills -g -y
πŸ“– Extracted from docs: dedalus-erp-pas/foundation-skills
31Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

Vue.js 3 best practices guidelines covering Composition API, component design, reactivity patterns, Tailwind CSS utility-first styling, PrimeVue component library integration, and code organization. This skill should be used when writing, reviewing, or refactoring Vue.js code to ensure idiomatic patterns and maintainable code.

Overview

# Vue.js Best Practices

Comprehensive best practices guide for Vue.js 3 applications. Contains guidelines across multiple categories to ensure idiomatic, maintainable, and scalable Vue.js code, including Tailwind CSS integration patterns for utility-first styling and PrimeVue component library best practices.

When to Apply

Reference these guidelines when:

  • Writing new Vue components or composables
  • Implementing features with Composition API
  • Reviewing code for Vue.js patterns compliance
  • Refactoring existing Vue.js code
  • Setting up component architecture
  • Working with Nuxt.js applications
  • Styling Vue components with Tailwind CSS utility classes
  • Creating design systems with Tailwind and Vue
  • Using PrimeVue component library
  • Customizing PrimeVue components with PassThrough API

Rule Categories

| Category | Focus | Prefix |

|----------|-------|--------|

| Composition API | Proper use of Composition API patterns | composition- |

| Component Design | Component structure and organization | component- |

| Reactivity | Reactive state management patterns | reactive- |

| Props & Events | Component communication patterns | props- |

| Template Patterns | Template syntax best practices | template- |

| Code Organization | Project and code structure | organization- |

| TypeScript | Type-safe Vue.js patterns | typescript- |

| Error Handling | Error boundaries and handling | error- |

| Tailwind CSS | Utility-first styling patterns | tailwind- |

| PrimeVue | Component library integration patterns | primevue- |

Quick Reference

1. Composition API Best Practices

  • composition-script-setup - Always use

    ```

    Composable Pattern

    Correct: Well-structured composable

    ```typescript

    // composables/useUser.ts

    import { ref, computed, watch } from 'vue'

    import type { Ref } from 'vue'

    import type { User } from '@/types'

    export function useUser(userId: Ref | string) {

    // State

    const user = ref(null)

    const loading = ref(false)

    const error = ref(null)

    // Computed

    const fullName = computed(() => {

    if (!user.value) return ''

    return ${user.value.firstName} ${user.value.lastName}

    })

    // Methods

    async function fetchUser(id: string) {

    loading.value = true

    error.value = null

    try {

    const response = await api.getUser(id)

    user.value = response.data

    } catch (e) {

    error.value = e as Error

    } finally {

    loading.value = false

    }

    }

    // Auto-fetch when userId changes (if reactive)

    if (isRef(userId)) {

    watch(userId, (newId) => fetchUser(newId), { immediate: true })

    } else {

    fetchUser(userId)

    }

    // Return

    return {

    user: readonly(user),

    fullName,

    loading: readonly(loading),

    error: readonly(error),

    refresh: () => fetchUser(unref(userId))

    }

    }

    ```

    Props with Defaults

    Correct: Typed props with defaults

    ```vue

    ```

    Event Handling

    Correct: Typed emits with payloads

    ```vue

    ```

    v-model Implementation

    Correct: Custom v-model with defineModel (Vue 3.4+)

    ```vue

    ```

    Correct: Custom v-model (Vue 3.3 and earlier)

    ```vue

    ```

    Template Ref Typing

    Correct: Typed template refs

    ```vue

    ```

    Provide/Inject with Types

    Correct: Type-safe provide/inject

    ```typescript

    // types/injection-keys.ts

    import type { InjectionKey, Ref } from 'vue'

    import type { User } from './user'

    export const UserKey: InjectionKey> = Symbol('user')

    // Parent component

    import { provide, ref } from 'vue'

    import { UserKey } from '@/types/injection-keys'

    const user = ref({ id: '1', name: 'John' })

    provide(UserKey, user)

    // Child component

    import { inject } from 'vue'

    import { UserKey } from '@/types/injection-keys'

    const user = inject(UserKey)

    if (!user) {

    throw new Error('User not provided')

    }

    ```

    Error Boundary Component

    Correct: Error boundary with onErrorCaptured

    ```vue

    ```

    Async Component Loading

    Correct: Async components with loading/error states

    ```typescript

    import { defineAsyncComponent } from 'vue'

    const AsyncDashboard = defineAsyncComponent({

    loader: () => import('./Dashboard.vue'),

    loadingComponent: LoadingSpinner,

    errorComponent: ErrorDisplay,

    delay: 200, // Show loading after 200ms

    timeout: 10000 // Timeout after 10s

    })

    ```

Tailwind CSS Best Practices

Vue's component-based architecture pairs naturally with Tailwind's utility-first approach. Follow these patterns for maintainable, consistent styling.

Utility-First Approach

Apply Tailwind utility classes directly in Vue templates for rapid, consistent styling:

Correct: Utility classes in template

```vue

```

Class Ordering Convention

Maintain consistent class ordering for readability. Recommended order:

  1. Layout - flex, grid, block, hidden
  2. Positioning - relative, absolute, fixed
  3. Box Model - w-, h-, m-, p-
  4. Typography - text-, font-, leading-
  5. Visual - bg-, border-, rounded-, shadow-
  6. Interactive - hover:, focus:, active:

Use the official Prettier plugin (prettier-plugin-tailwindcss) to automatically sort classes.

Responsive Design (Mobile-First)

Use Tailwind's responsive prefixes for mobile-first responsive design:

Correct: Mobile-first responsive layout

```vue

```

Breakpoint Reference:

  • sm: - 640px and up
  • md: - 768px and up
  • lg: - 1024px and up
  • xl: - 1280px and up
  • 2xl: - 1536px and up

State Variants

Use state variants for interactive elements:

Correct: State variants for buttons

```vue

```

Dark Mode Support

Use the dark: prefix for dark mode styles:

Correct: Dark mode support

```vue

```

Dynamic Classes with Computed Properties

Use computed properties for conditional class binding:

Correct: Computed classes for variants

```vue

```

Class Variance Authority (CVA) Pattern

For complex component variants, use the CVA pattern with a helper library:

Correct: CVA-style variant management

```vue

```

Component Extraction for Reusable Patterns

Extract repeated utility patterns into Vue components:

Correct: Reusable card component

```vue

```

Tailwind Configuration with Design Tokens

Define design tokens in your Tailwind config for consistency:

Correct: tailwind.config.js with design tokens

```javascript

/* @type {import('tailwindcss').Config} /

export default {

content: ['./index.html', './src/*/.{vue,js,ts,jsx,tsx}'],

theme: {

extend: {

colors: {

// Semantic color tokens

primary: {

50: '#eff6ff',

100: '#dbeafe',

500: '#3b82f6',

600: '#2563eb',

700: '#1d4ed8'

},

surface: {

light: '#ffffff',

dark: '#1f2937'

}

},

spacing: {

// Custom spacing tokens

'4.5': '1.125rem',

'18': '4.5rem'

},

fontFamily: {

sans: ['Inter', 'system-ui', 'sans-serif']

},

borderRadius: {

'4xl': '2rem'

}

}

},

plugins: []

}

```

Tailwind CSS v4 Configuration

For Tailwind CSS v4, use the CSS-first configuration approach:

Correct: Tailwind v4 CSS configuration

```css

/ main.css /

@import "tailwindcss";

@theme {

/ Custom colors /

--color-primary-500: #3b82f6;

--color-primary-600: #2563eb;

--color-primary-700: #1d4ed8;

/ Custom spacing /

--spacing-4-5: 1.125rem;

--spacing-18: 4.5rem;

/ Custom fonts /

--font-family-sans: 'Inter', system-ui, sans-serif;

}

```

Using `cn()` Helper for Conditional Classes

Use a class merging utility for conditional classes:

Correct: cn() helper with clsx and tailwind-merge

```typescript

// utils/cn.ts

import { clsx, type ClassValue } from 'clsx'

import { twMerge } from 'tailwind-merge'

export function cn(...inputs: ClassValue[]) {

return twMerge(clsx(inputs))

}

```

Usage in component:

```vue

```

PrimeVue Best Practices

PrimeVue is a comprehensive Vue UI component library with 90+ components. Follow these patterns for effective integration and customization.

Installation & Setup

Correct: PrimeVue v4 setup with Vue 3

```typescript

// main.ts

import { createApp } from 'vue'

import PrimeVue from 'primevue/config'

import Aura from '@primevue/themes/aura'

import App from './App.vue'

const app = createApp(App)

app.use(PrimeVue, {

theme: {

preset: Aura,

options: {

darkModeSelector: '.dark-mode'

}

}

})

app.mount('#app')

```

Correct: Component registration (tree-shakeable)

```typescript

// main.ts - Register only components you use

import Button from 'primevue/button'

import DataTable from 'primevue/datatable'

import Column from 'primevue/column'

app.component('Button', Button)

app.component('DataTable', DataTable)

app.component('Column', Column)

```

PassThrough (PT) API

The PassThrough API allows customization of internal DOM elements without modifying component source:

Correct: Component-level PassThrough

```vue

```

Correct: Dynamic PassThrough with state

```vue

```

Global PassThrough Configuration

Define shared styles at the application level:

Correct: Global PT configuration

```typescript

// main.ts

import PrimeVue from 'primevue/config'

import Aura from '@primevue/themes/aura'

app.use(PrimeVue, {

theme: {

preset: Aura

},

pt: {

// All buttons get consistent styling

button: {

root: {

class: 'rounded-lg font-medium transition-all duration-200'

}

},

// All inputs get consistent styling

inputtext: {

root: {

class: 'rounded-lg border-2 focus:ring-2 focus:ring-primary-500'

}

},

// All panels share styling

panel: {

header: {

class: 'bg-surface-50 dark:bg-surface-900'

}

},

// Global CSS injection

global: {

css: `

.p-component {

font-family: 'Inter', sans-serif;

}

`

}

}

})

```

usePassThrough Utility

Extend existing presets with custom modifications:

Correct: Extending Tailwind preset

```typescript

// presets/custom-tailwind.ts

import { usePassThrough } from 'primevue/passthrough'

import Tailwind from 'primevue/passthrough/tailwind'

export const CustomTailwind = usePassThrough(

Tailwind,

{

panel: {

header: {

class: ['bg-gradient-to-r from-primary-500 to-primary-600']

},

title: {

class: ['text-white font-bold']

}

},

button: {

root: {

class: ['shadow-lg hover:shadow-xl transition-shadow']

}

}

},

{

mergeSections: true, // Keep original sections

mergeProps: false // Replace props (don't merge arrays)

}

)

```

Merge Strategy Reference:

| mergeSections | mergeProps | Behavior |

|---------------|------------|----------|

| true | false | Custom value replaces original (default) |

| true | true | Custom values merge with original |

| false | true | Only custom sections included |

| false | false | Minimal - only custom sections, no merging |

Unstyled Mode with Tailwind

Use unstyled PrimeVue components with full Tailwind control:

Correct: Unstyled mode configuration

```typescript

// main.ts

import PrimeVue from 'primevue/config'

app.use(PrimeVue, {

unstyled: true // Remove all default styles

})

```

Correct: Custom styled button with unstyled mode

```vue

```

Wrapper Components Pattern

Create reusable wrapper components for consistent styling:

Correct: Button wrapper component

```vue

```

Usage:

```vue

```

DataTable Best Practices

Correct: Typed DataTable with Composition API

```vue

```

Form Components Pattern

Correct: Form with validation using PrimeVue

```vue

```

Dialog & Overlay Patterns

Correct: Confirmation dialog with composable

```typescript

// composables/useConfirmDialog.ts

import { useConfirm } from 'primevue/useconfirm'

export function useConfirmDialog() {

const confirm = useConfirm()

function confirmDelete(

message: string,

onAccept: () => void,

onReject?: () => void

) {

confirm.require({

message,

header: 'Confirm Delete',

icon: 'pi pi-exclamation-triangle',

rejectClass: 'p-button-secondary p-button-outlined',

acceptClass: 'p-button-danger',

rejectLabel: 'Cancel',

acceptLabel: 'Delete',

accept: onAccept,

reject: onReject

})

}

function confirmAction(options: {

message: string

header: string

onAccept: () => void

onReject?: () => void

}) {

confirm.require({

message: options.message,

header: options.header,

icon: 'pi pi-info-circle',

rejectClass: 'p-button-secondary p-button-outlined',

acceptClass: 'p-button-primary',

accept: options.onAccept,

reject: options.onReject

})

}

return {

confirmDelete,

confirmAction

}

}

```

Usage:

```vue

```

Toast Notifications

Correct: Toast service with composable

```typescript

// composables/useNotifications.ts

import { useToast } from 'primevue/usetoast'

export function useNotifications() {

const toast = useToast()

function success(summary: string, detail?: string) {

toast.add({

severity: 'success',

summary,

detail,

life: 3000

})

}

function error(summary: string, detail?: string) {

toast.add({

severity: 'error',

summary,

detail,

life: 5000

})

}

function warn(summary: string, detail?: string) {

toast.add({

severity: 'warn',

summary,

detail,

life: 4000

})

}

function info(summary: string, detail?: string) {

toast.add({

severity: 'info',

summary,

detail,

life: 3000

})

}

return { success, error, warn, info }

}

```

Accessibility Best Practices

PrimeVue components are WCAG 2.0 compliant. Ensure proper usage:

Correct: Accessible form fields

```vue

```

Lazy Loading Components

Correct: Async component loading for large PrimeVue components

```typescript

// components/lazy/index.ts

import { defineAsyncComponent } from 'vue'

export const LazyDataTable = defineAsyncComponent({

loader: () => import('primevue/datatable'),

loadingComponent: () => import('@/components/ui/TableSkeleton.vue'),

delay: 200

})

export const LazyEditor = defineAsyncComponent({

loader: () => import('primevue/editor'),

loadingComponent: () => import('@/components/ui/EditorSkeleton.vue'),

delay: 200

})

export const LazyChart = defineAsyncComponent({

loader: () => import('primevue/chart'),

loadingComponent: () => import('@/components/ui/ChartSkeleton.vue'),

delay: 200

})

```

Anti-Patterns to Avoid

Don't Mutate Props

Incorrect:

```vue

```

Correct:

```vue

```

Don't Use v-if with v-for

Incorrect:

```vue

```

Correct:

```vue

```

Don't Store Derived State

Incorrect:

```vue

```

Correct:

```vue

```

Don't Destructure Reactive Objects

Incorrect:

```vue

```

Correct:

```vue

```

Don't Concatenate Tailwind Class Names

Dynamic class concatenation breaks Tailwind's compiler and classes get purged in production:

Incorrect:

```vue

```

Correct:

```vue

```

Don't Overuse @apply

Excessive @apply usage defeats the purpose of utility-first CSS:

Incorrect:

```css

/ styles.css /

.card {

@apply mx-auto max-w-md rounded-xl bg-white p-6 shadow-lg;

}

.card-title {

@apply text-xl font-semibold text-gray-900;

}

.card-description {

@apply mt-2 text-gray-600;

}

.card-button {

@apply mt-4 rounded-md bg-blue-600 px-4 py-2 text-white hover:bg-blue-700;

}

```

Correct: Use Vue components instead

```vue

```

Don't Use Conflicting Utilities

Applying multiple utilities that target the same CSS property causes unpredictable results:

Incorrect:

```vue

```

Correct:

```vue

```

Don't Ignore Accessibility

Always include proper accessibility attributes alongside visual styling:

Incorrect:

```vue

```

Correct:

```vue

```

Don't Create Overly Long Class Strings

Break down complex class combinations into logical groups or components:

Incorrect:

```vue

```

Correct: Extract to component or use computed

```vue

```

Don't Override PrimeVue Styles with CSS

Using CSS overrides bypasses the design system and causes maintenance issues:

Incorrect:

```css

/ styles.css - Avoid this approach /

.p-button {

background-color: #3b82f6 !important;

border-radius: 8px !important;

}

.p-datatable .p-datatable-thead > tr > th {

background: #f3f4f6 !important;

}

```

Correct: Use design tokens or PassThrough

```typescript

// main.ts - Use design tokens

app.use(PrimeVue, {

theme: {

preset: Aura,

options: {

cssLayer: {

name: 'primevue',

order: 'tailwind-base, primevue, tailwind-utilities'

}

}

},

pt: {

button: {

root: { class: 'rounded-lg' }

}

}

})

```

Don't Import Entire PrimeVue Library

Importing everything bloats bundle size:

Incorrect:

```typescript

// main.ts - Don't do this

import PrimeVue from 'primevue/config'

import * as PrimeVueComponents from 'primevue' // Imports everything!

Object.entries(PrimeVueComponents).forEach(([name, component]) => {

app.component(name, component)

})

```

Correct: Import only what you need

```typescript

// main.ts - Tree-shakeable imports

import Button from 'primevue/button'

import DataTable from 'primevue/datatable'

import Column from 'primevue/column'

app.component('Button', Button)

app.component('DataTable', DataTable)

app.component('Column', Column)

```

Don't Mix Styled and Unstyled Inconsistently

Mixing modes creates visual inconsistency:

Incorrect:

```typescript

// main.ts

app.use(PrimeVue, {

unstyled: true // Global unstyled

})

// SomeComponent.vue - Using styled component anyway

Nuxt.js Specific Guidelines

When using Nuxt.js, follow these additional patterns:

  • Auto-imports: Leverage Nuxt's auto-imports for Vue APIs and composables
  • useFetch/useAsyncData: Use Nuxt's data fetching composables for SSR-compatible data loading
  • definePageMeta: Use for page-level metadata and middleware
  • Server routes: Use server/api/ for API endpoints
  • Runtime config: Use useRuntimeConfig() for environment variables

References

Vue.js

  • [Vue.js Documentation](https://vuejs.org)
  • [Vue.js Style Guide](https://vuejs.org/style-guide/)
  • [Composition API FAQ](https://vuejs.org/guide/extras/composition-api-faq.html)
  • [VueUse - Collection of Vue Composition Utilities](https://vueuse.org)
  • [Nuxt Documentation](https://nuxt.com)
  • [Pinia Documentation](https://pinia.vuejs.org)

Tailwind CSS

  • [Tailwind CSS Documentation](https://tailwindcss.com/docs)
  • [Styling with Utility Classes](https://tailwindcss.com/docs/styling-with-utility-classes)
  • [Tailwind CSS v4 Release](https://tailwindcss.com/blog/tailwindcss-v4)
  • [Class Variance Authority (CVA)](https://cva.style/docs)
  • [tailwind-merge](https://github.com/dcastil/tailwind-merge)
  • [prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss)
  • [Vue School - Tailwind CSS Fundamentals](https://vueschool.io/cour

More from this repository10

🎯
react-best-practices🎯Skill

Guides developers in writing high-performance, modern React and Next.js applications by providing best practices for component architecture, performance, and UI design.

🎯
gitlab code review🎯Skill

gitlab code review skill from dedalus-erp-pas/foundation-skills

🎯
postgres🎯Skill

postgres skill from dedalus-erp-pas/foundation-skills

🎯
article-extractor🎯Skill

article-extractor skill from dedalus-erp-pas/foundation-skills

🎯
frontend-design🎯Skill

Crafts distinctive, production-grade frontend interfaces with exceptional design quality, generating creative and polished web components and UI layouts.

🎯
create-design-system-rules🎯Skill

Generates customized design system rules to automate Figma-to-code workflows, ensuring consistent UI/UX conventions and patterns across design and development teams.

🎯
changelog-generator🎯Skill

Generates professional, user-friendly changelogs by automatically transforming git commits into clear, categorized release notes.

🎯
web-design-guidelines🎯Skill

Performs comprehensive web UI review by analyzing code, accessibility, and design against industry guidelines with auto-fix capabilities.

🎯
playwright-skill🎯Skill

Automates web testing and browser interactions using Playwright, enabling comprehensive website validation, form testing, and dynamic web application debugging.

🎯
mcp-builder🎯Skill

Builds high-quality MCP servers that enable LLMs to interact with external services through well-designed, discoverable, and context-aware tools.