All skills
vuejs-ai avatar

/vue-pinia-best-practices

@bc922e4 official
by Vue AIvuejs-ai/skills2.9k stars
167

Pinia stores, state management patterns, store setup, and reactivity with stores.

Use this Skill: https://skilld.dev/gh/vuejs-ai/skills/vue-pinia-best-practices

This session only. Nothing lands on disk.

referencestate-use-pinia-for-large-apps.md

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

Use Pinia for Large-Scale Vue Applications

Impact: MEDIUM - While Vue's Composition API allows creating simple reactive stores with reactive() and ref(), these hand-rolled solutions lack the tooling, conventions, and debugging capabilities needed for large-scale production applications. Pinia is the official Vue state management solution and should be used for any non-trivial application.

Task Checklist

  • Use Pinia for applications with shared state across multiple components
  • Use Pinia when team collaboration requires consistent patterns
  • Use Pinia when you need Vue DevTools state debugging
  • Hand-rolled reactive() is acceptable only for simple, single-developer apps
  • Migrate from Vuex to Pinia (Vuex is in maintenance mode)

When Hand-Rolled State is Acceptable

Simple reactive state is fine for:

  • Prototypes and proof-of-concepts
  • Very small applications with minimal shared state
  • Single-developer projects with limited scope
  • Learning purposes
// Simple hand-rolled store - OK for small apps
import { reactive, readonly } from 'vue'

export const store = reactive({
  count: 0,
  increment() {
    this.count++
  }
})

When to Use Pinia

Use Pinia when you have any of these requirements:

1. DevTools Integration

Pinia provides rich Vue DevTools support:

  • Timeline of state changes
  • State inspection and editing
  • Time-travel debugging
  • Action tracking
// Pinia store - fully visible in DevTools
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  actions: {
    increment() {
      this.count++  // Tracked in DevTools timeline
    }
  }
})

2. TypeScript Support

Pinia has excellent TypeScript inference:

// Full type inference without extra configuration
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    name: '',
    age: 0,
    preferences: {
      theme: 'light' as 'light' | 'dark'
    }
  }),

  getters: {
    // Return type is inferred
    displayName: (state) => state.name || 'Anonymous'
  },

  actions: {
    // Full parameter type checking
    setUser(name: string, age: number) {
      this.name = name
      this.age = age
    }
  }
})

// Usage is fully typed
const userStore = useUserStore()
userStore.name  // string
userStore.displayName  // string
userStore.setUser('John', 30)  // Type-checked

3. Team Collaboration

Pinia enforces conventions that help teams:

// Consistent structure across all stores
// stores/products.js
export const useProductsStore = defineStore('products', {
  state: () => ({ /* ... */ }),
  getters: { /* ... */ },
  actions: { /* ... */ }
})

// stores/cart.js - Same structure
export const useCartStore = defineStore('cart', {
  state: () => ({ /* ... */ }),
  getters: { /* ... */ },
  actions: { /* ... */ }
})

4. Hot Module Replacement (HMR)

Pinia supports HMR out of the box - state persists during development:

// State survives code changes during development
// No need to re-login or re-create state after every edit

5. Server-Side Rendering (SSR)

Pinia handles SSR state correctly:

// Automatic per-request state isolation
// State serialization for hydration
// No cross-request pollution

6. Plugin Ecosystem

Pinia supports plugins for common needs:

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

// Now stores can persist to localStorage
export const useSettingsStore = defineStore('settings', {
  state: () => ({
    theme: 'light',
    language: 'en'
  }),
  persist: true  // Automatically saved/restored
})

Pinia vs Hand-Rolled Comparison

Feature Hand-Rolled reactive() Pinia
DevTools integration No Yes
TypeScript inference Manual Automatic
HMR support No Yes
SSR support Manual Built-in
Plugins No Yes
Time-travel debugging No Yes
Learning curve Lower Slightly higher
Bundle size Smaller ~1KB
Team conventions None Enforced

Migration from Vuex

Vuex is now in maintenance mode. Migrate to Pinia for new features:

// Vuex (legacy)
export default createStore({
  state: { count: 0 },
  mutations: {
    INCREMENT(state) { state.count++ }
  },
  actions: {
    increment({ commit }) { commit('INCREMENT') }
  }
})

// Pinia (recommended)
export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  actions: {
    increment() { this.count++ }  // No mutations needed!
  }
})

Pinia advantages over Vuex:

  • No mutations (simpler mental model)
  • Better TypeScript support
  • No nested modules complexity
  • Smaller bundle size
  • Composition API style available

Pinia Store Styles

Choose the style that fits your team:

Options Style (Similar to Options API)

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: {
    double: (state) => state.count * 2
  },
  actions: {
    increment() { this.count++ }
  }
})

Setup Style (Composition API)

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const double = computed(() => count.value * 2)
  function increment() { count.value++ }

  return { count, double, increment }
})

Quick Start

npm install pinia
// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)
app.use(createPinia())
app.mount('#app')

Reference

Source: SKILL.md on GitHub

No alerts16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill provides educational content and best practices for Pinia state management in Vue.js applications. It is a documentation-focused skill with no malicious patterns detected.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer7mo

    7 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

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

Last checked against GitHub 2 months ago.

Steadyupdated 8 months ago
version
1.0.0
author
github.com/vuejs-ai
  • Vue
  • pinia
  • state-management
  • reactivity
  • store-setup
  • devtools
  • ssr

README badge

README badge for vuejs-ai/skills/vue-pinia-best-practices

Provides Pinia store setup patterns, reactivity gotchas, and state management conventions for Vue apps. Covers destructuring pitfalls, DevTools integration, SSR considerations, and filter persistence strategies.

Generated from the current SKILL.md.

Does this skill cover setup stores and options stores?
Yes. The skill addresses both patterns, including common issues like setup stores missing state in DevTools or SSR, and provides guidance on when to use each.
What reactivity issues does this skill handle?
It covers store destructuring breaking reactivity, method binding losing context in templates, and how to maintain reactive updates when accessing store properties.
Does this skill address SSR or DevTools integration?
Yes. It includes troubleshooting for setup stores not exposing state correctly in DevTools and SSR environments.
Does this cover ephemeral state like filters or URL sync?
Yes. The skill includes patterns for handling filters that reset on refresh and guidance on syncing state with URLs for shareable application state.

Generated from the current SKILL.md. These answers refresh after source changes.