All skills
onmax avatar

/vue-best-practices

@de09c7b official
by Maxonmax/nuxt-skills715 stars
38

MUST be used for Vue.js tasks. Strongly recommends Composition API with `<script setup>` and TypeScript as the standard approach. Covers Vue 3, SSR, Volar, vue-tsc. Load for any Vue, .vue files, Vue Router, Pinia, or Vite with Vue work. ALWAYS use Composition API unless the project explicitly requires Options API.

Use this Skill: https://skilld.dev/gh/onmax/nuxt-skills/vue-best-practices

This session only. Nothing lands on disk.

referencesstate-management.md

≈846 tokens on demand. Your agent reads this file only when SKILL.md points to it.

State Management Strategy

Impact: HIGH - Use the lightest state solution that fits your app architecture. SPA-only apps can use lightweight global composables, while SSR/Nuxt apps should default to Pinia for request-safe isolation and predictable tooling.

Task List

  • Keep state local first, then promote to shared/global only when needed
  • Use singleton composables only in non-SSR applications
  • Expose global state as readonly and mutate through explicit actions
  • Prefer Pinia for SSR/Nuxt, large apps, and advanced debugging/plugin needs
  • Avoid exporting mutable module-level reactive state directly

Choose the Lightest Store Approach

  • Feature composable: Default for reusable logic with local/feature-level state.
  • Singleton composable or VueUse createGlobalState: Small non-SSR apps needing shared app state.
  • Pinia: SSR/Nuxt apps, medium-to-large apps, and cases requiring DevTools, plugins, or action tracing.

Avoid Exporting Mutable Module State

BAD:

// store/cart.ts
import { reactive } from 'vue'

export const cart = reactive({
  items: [] as Array<{ id: string; qty: number }>
})

GOOD:

// composables/useCartStore.ts
import { reactive, readonly } from 'vue'

let _store: ReturnType<typeof createCartStore> | null = null

function createCartStore() {
  const state = reactive({
    items: [] as Array<{ id: string; qty: number }>
  })

  function addItem(id: string, qty = 1) {
    const existing = state.items.find((item) => item.id === id)
    if (existing) {
      existing.qty += qty
      return
    }
    state.items.push({ id, qty })
  }

  return {
    state: readonly(state),
    addItem
  }
}

export function useCartStore() {
  if (!_store) _store = createCartStore()
  return _store
}

Do Not Use Runtime Singletons in SSR

Module singletons live for the runtime lifetime. In SSR this can leak state between requests.

BAD:

// shared singleton reused across requests
const cartStore = useCartStore()

export function useServerCart() {
  return cartStore
}

GOOD:

pinia dependency required.

// stores/cart.ts
import { defineStore } from 'pinia'

export const useCartStore = defineStore('cart', {
  state: () => ({
    items: [] as Array<{ id: string; qty: number }>
  }),
  actions: {
    addItem(id: string, qty = 1) {
      const existing = this.items.find((item) => item.id === id)
      if (existing) {
        existing.qty += qty
        return
      }
      this.items.push({ id, qty })
    }
  }
})

Use createGlobalState for Small SPA Global State

@vueuse/core dependency required.

If the app is non-SSR and already uses VueUse, createGlobalState removes singleton boilerplate.

import { createGlobalState } from '@vueuse/core'
import { computed, ref } from 'vue'

export const useAuthState = createGlobalState(() => {
  const token = ref<string | null>(null)
  const isAuthenticated = computed(() => token.value !== null)

  function setToken(next: string | null) {
    token.value = next
  }

  return {
    token,
    isAuthenticated,
    setToken
  }
})

Source: SKILL.md on GitHub

No alerts9d3 checks · Risk SAFE
  • Gen Agent Trust Hub9d

    This skill provides a detailed set of best practices for Vue.js development, focusing on performance, state management, and component architecture. It includes security-conscious advice regarding the sanitization of HTML content. A minor security observation is noted regarding the potential for indirect prompt injection when handling untrusted user input, although the skill proactively provides mitigations for this risk.

  • Socket9d

    No alerts

  • Snyk9d

    Risk: LOW · No issues

Signed by skilld at de09c7b. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated last week
metadata
{
  "author": "github.com/vuejs-ai",
  "version": "18.0.0"
}

README badge

README badge for onmax/nuxt-skills/vue-best-practices