From web-state-pinia
Pinia stores, Vue 3 state patterns. Use when managing client state in Vue applications, choosing between Options/Setup stores, composing stores, or implementing persistence.
How this skill is triggered — by the user, by Claude, or both
Slash command
/web-state-pinia:web-state-piniaThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> **Quick Guide:** Use Pinia for all shared client state in Vue 3. Options stores for simplicity, Setup stores for flexibility. Server data? Use your data fetching solution. Use `storeToRefs()` when destructuring state.
Quick Guide: Use Pinia for all shared client state in Vue 3. Options stores for simplicity, Setup stores for flexibility. Server data? Use your data fetching solution. Use
storeToRefs()when destructuring state.
<critical_requirements>
(You MUST use a data fetching solution for ALL server/API data - NEVER put API responses in Pinia stores)
(You MUST use storeToRefs() when destructuring state from stores - direct destructuring loses reactivity)
(You MUST return ALL state properties in Setup stores - private state breaks SSR and DevTools)
(You MUST use named exports ONLY - NO default exports in any store files)
(You MUST use named constants for ALL numbers - NO magic numbers in state code)
</critical_requirements>
Auto-detection: Pinia, defineStore, Vue 3 state, storeToRefs, Vue state management, Options store, Setup store
When to use:
When NOT to use:
ref() or reactive())Pinia is the official state management solution for Vue 3, designed to be intuitive, type-safe, and flexible. It eliminates the boilerplate of Vuex while maintaining powerful features like DevTools integration, plugin support, and SSR compatibility.
Core Principles:
<script setup>State Ownership:
| State Type | Solution | Reason |
|---|---|---|
| Server/API data | Data fetching solution | Caching, synchronization, loading states |
| Shared client state | Pinia | Reactivity, DevTools, persistence |
| Component-local state | ref() / reactive() | Simpler, no overhead |
| URL state (filters) | Route query params | Shareable, bookmarkable |
Pinia offers two store definition syntaxes. Choose based on your needs.
Which store syntax should I use?
Need composables (useRoute, useI18n)?
├─ YES → Setup Store
└─ NO → Need watchers inside store?
├─ YES → Setup Store
└─ NO → Prefer Vue Options API style?
├─ YES → Options Store
└─ NO → Setup Store (more flexible)
Options Store: Simpler, familiar to Vuex users, built-in $reset() method
Setup Store: More flexible, supports composables, requires manual reset
For implementation examples, see examples/core.md.
Use Options stores for straightforward state management with familiar syntax.
$reset() method is neededFor implementation examples and good/bad comparisons, see examples/core.md.
Use Setup stores when you need maximum flexibility and composable integration.
useRoute, useRouter)useI18n)ref() for state, computed() for getters$reset() if neededFor implementation examples, see examples/core.md.
Proper store access patterns prevent reactivity issues.
storeToRefs() for state/getters - preserves reactivityFor implementation examples with storeToRefs, see examples/core.md.
Stores can use other stores, but follow rules to avoid circular dependencies.
For implementation examples, see examples/core.md.
Use plugins for persisting state across sessions.
pinia-plugin-persistedstate for most casespick option to persist specific properties onlyFor implementation examples, see examples/persistence.md.
Extend all stores with shared functionality.
For implementation examples, see examples/plugins.md.
Test stores in isolation and within components.
setActivePinia()createTestingPinia() for component mounting@pinia/testingFor implementation examples, see examples/testing.md.
Handle server-side rendering and hydration properly.
typeof window !== "undefined" checksFor implementation examples, see examples/ssr.md.
<red_flags>
High Priority Issues:
storeToRefs() - silently breaks reactivity, UI shows stale datalocalStorage, window) - crashes SSRGotchas & Edge Cases:
storeToRefs() works for state and getters only, not actions - destructure actions directly$reset(), Setup stores do not - implement manually or use a plugin$patch with a function allows accessing current state: store.$patch(state => { state.items.push(item) })this - use function keyword or state parameterFor complete anti-pattern examples, see reference.md.
</red_flags>
Detailed Resources:
<critical_reminders>
(You MUST use a data fetching solution for ALL server/API data - NEVER put API responses in Pinia stores)
(You MUST use storeToRefs() when destructuring state from stores - direct destructuring loses reactivity)
(You MUST return ALL state properties in Setup stores - private state breaks SSR and DevTools)
(You MUST use named exports ONLY - NO default exports in any store files)
(You MUST use named constants for ALL numbers - NO magic numbers in state code)
Failure to follow these rules will cause reactivity bugs, SSR hydration errors, and DevTools failures.
</critical_reminders>
npx claudepluginhub agents-inc/skills --plugin web-state-piniaManage shared application state with Pinia stores using Options or Setup syntax. Includes DevTools support, type safety, and lazy loading.
Manages Vue 3 state with Pinia v3 stores, covering defineStore, getters, actions, SSR hydration, and testing.
Guides Pinia store setup, reactivity patterns, and state management in Vue apps. Covers common errors like 'getActivePinia was called' and destructuring issues.