Agent skill
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.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/web-state-pinia
SKILL.md
Pinia State Management Patterns
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>
CRITICAL: Before Managing State with Pinia
(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:
- Managing shared client state in Vue 3 applications
- Choosing between Options stores and Setup stores
- Composing stores that depend on each other
- Implementing state persistence across sessions
- Adding DevTools integration for debugging
- Setting up stores for SSR applications
When NOT to use:
- Server/API data (use a dedicated data fetching solution)
- Simple component-local state (use
ref()orreactive()) - URL-appropriate state like filters (use route query params)
Philosophy
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:
- Modular by Default - Each store is independent, no nested modules
- No Mutations - Actions handle all state changes directly
- Full TypeScript Support - Type inference works out of the box
- Composition API Friendly - Works seamlessly with
<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 |
Core Patterns
Pattern 1: Options Store vs Setup Store Decision
Pinia offers two store definition syntaxes. Choose based on your needs.
Decision Tree
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.
Pattern 2: Options Store Definition
Use Options stores for straightforward state management with familiar syntax.
When to Use
- Teams familiar with Vuex or Vue Options API
- Simple stores without composable dependencies
- When built-in
$reset()method is needed - Standard CRUD operations on client state
For implementation examples and good/bad comparisons, see examples/core.md.
Pattern 3: Setup Store Definition
Use Setup stores when you need maximum flexibility and composable integration.
When to Use
- Using Vue Router composables (
useRoute,useRouter) - Using i18n composables (
useI18n) - Need watchers inside the store
- Complex computed dependencies
- Integrating with external composables
Critical Requirements for Setup Stores
- Return ALL state properties (no private state)
- Use
ref()for state,computed()for getters - Functions become actions automatically
- Must implement custom
$reset()if needed
For implementation examples, see examples/core.md.
Pattern 4: Accessing Store State in Components
Proper store access patterns prevent reactivity issues.
Key Rules
- Never destructure state directly - loses reactivity
- Use
storeToRefs()for state/getters - preserves reactivity - Destructure actions directly - they don't need reactivity
For implementation examples with storeToRefs, see examples/core.md.
Pattern 5: Composing Stores
Stores can use other stores, but follow rules to avoid circular dependencies.
Guidelines
- Import and use stores at the top of your store function
- Avoid circular dependencies through getters/actions
- If stores reference each other, ensure no infinite loops
- Use setup stores for complex composition patterns
For implementation examples, see examples/core.md.
Pattern 6: State Persistence
Use plugins for persisting state across sessions.
Persistence Guidelines
- Use
pinia-plugin-persistedstatefor most cases - Only persist user preferences and non-sensitive data
- Use
pickoption to persist specific properties only - Never persist server data (refetch on load instead)
- Consider storage type: localStorage vs sessionStorage
For implementation examples, see examples/persistence.md.
Pattern 7: Pinia Plugins
Extend all stores with shared functionality.
Common Plugin Use Cases
- Adding shared properties (router, analytics)
- Wrapping actions with logging/timing
- Adding custom options (debounce, throttle)
- Implementing side effects (localStorage)
For implementation examples, see examples/plugins.md.
Pattern 8: Testing Stores
Test stores in isolation and within components.
Testing Approaches
- Unit tests: Test store actions/getters directly with
setActivePinia() - Component tests: Use
createTestingPinia()for component mounting - Mocking: Actions are stubbed by default with
@pinia/testing
For implementation examples, see examples/testing.md.
Pattern 9: SSR Considerations
Handle server-side rendering and hydration properly.
SSR Guidelines
- Use SSR-safe defaults (no browser APIs in initial state)
- Guard client-only logic with
typeof window !== "undefined"checks - Be careful with Setup stores - ensure all refs are returned
- Sanitize serialized state to prevent XSS
For implementation examples, see examples/ssr.md.
<red_flags>
RED FLAGS
High Priority Issues:
- Storing server/API data in Pinia instead of using a data fetching solution - causes stale data, no caching, manual sync
- Destructuring state without
storeToRefs()- silently breaks reactivity, UI shows stale data - Private state in Setup stores (not returning all refs) - breaks SSR hydration, DevTools, and plugins
- Browser APIs in state initialization (
localStorage,window) - crashes SSR
Gotchas & Edge Cases:
storeToRefs()works for state and getters only, not actions - destructure actions directly- Options stores have built-in
$reset(), Setup stores do not - implement manually or use a plugin - Store instances are singletons per Pinia instance - in SSR, each request needs its own Pinia
$patchwith a function allows accessing current state:store.$patch(state => { state.items.push(item) })- Arrow functions in Options store getters have no
this- usefunctionkeyword or state parameter
For complete anti-pattern examples, see reference.md.
</red_flags>
Detailed Resources:
- examples/core.md - Options store, Setup store, storeToRefs, composing stores
- examples/persistence.md - Selective persistence with pinia-plugin-persistedstate
- examples/testing.md - Unit testing stores, component testing with createTestingPinia
- examples/plugins.md - Logger plugin, reset plugin for Setup stores
- examples/ssr.md - SSR-safe stores, hydration, client-only guards
- reference.md - Decision frameworks, anti-patterns, TypeScript patterns, performance tips
<critical_reminders>
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>
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?