secondsky/claude-skills/pinia-v3
- community
Checking that the SKILL.md file is still in the repository.
Pinia v3 Vue state management with defineStore, getters, actions. Use for Vue 3 stores, Nuxt SSR, Vuex migration, or encountering store composition, hydration, testing errors.
Install
npx vskill@latest install secondsky/claude-skills/pinia-v3SKILL.md
Pinia v3 - Vue State Management
Status: Production Ready ✅ Last Updated: 2025-11-11 Dependencies: Vue 3 (or Vue 2.7 with @vue/composition-api) Latest Versions: pinia@^3.0.4, @pinia/nuxt@^0.11.2, @pinia/testing@^1.0.2
Quick Start (5 Minutes)
1. Install Pinia
For Vue <2.7 users: Also install @vue/composition-api with bun add @vue/composition-api
Why this matters:
- Pinia is the official Vue state management library
- Provides better TypeScript support than Vuex
- Eliminates mutations and namespacing complexity
- Full DevTools support with time-travel debugging
2. Create and Register Pinia Instance
CRITICAL:
- Install Pinia BEFORE using any store
- Call
app.use(pinia)before mounting the app - Only one Pinia instance per application (unless SSR)
3. Define Your First Store
4. Use Store in Components
The Two Store Syntaxes
Load `references/store-syntax-guide.md` for complete comparison of Option vs Setup stores.
Quick Overview
Pinia supports two store definition syntaxes:
Option Stores:
- Similar to Vue Options API
- Built-in
$reset()method - Best for: Simpler use cases, teams familiar with Vuex
Setup Stores:
- Uses Composition API pattern
- Full composables integration
- Best for: Advanced patterns, need watchers/VueUse integration
→ Load `references/store-syntax-guide.md` for: Complete syntax comparison, examples, choosing criteria
State, Getters, and Actions
Load `references/state-getters-actions.md` for complete API reference.
Quick Reference
State:
- Define in
state: () => ({...})(option) orref()(setup) - Access directly:
store.count - Mutate directly:
store.count++orstore.$patch({...}) - Reset:
store.$reset()(option stores only)
Getters:
- Computed properties:
getters: { double: (state) => state.count * 2 } - Access other getters with
this(must type return value)
Actions:
- Business logic:
actions: { increment() { this.count++ } } - Can be async
- Access other stores directly
Store Destructuring:
→ Load `references/state-getters-actions.md` for: Complete API, subscriptions, store composition patterns, Options API usage
Plugins and Composables
Load `references/plugins-composables.md` for complete plugin and composables guide.
Plugin Basics
Composables Integration
Option Stores: Limited to useLocalStorage style in state() Setup Stores: Full VueUse/composables support
→ Load `references/plugins-composables.md` for: Complete plugin patterns, VueUse integration, TypeScript typing, common patterns (persistence, router, logger)
Using Stores Outside Components
The Problem
Stores need the Pinia instance, which is auto-injected in components but not available in module scope.
❌ Wrong: Accessing Store at Module Level
✅ Right: Accessing Store Inside Callbacks
Why it works: Router guards execute AFTER app.use(pinia) completes.
SSR: Explicit Pinia Instance
Server-Side Rendering & Nuxt
Load `references/ssr-and-nuxt.md` for complete SSR and Nuxt integration guide.
SSR Quick Reference
State Hydration:
- Server: Serialize with
devalue()(notJSON.stringify) - Client: Hydrate BEFORE calling
useStore() - Critical: Call all
useStore()BEFOREawaitin actions
Nuxt 3/4 Integration
Auto-imports: defineStore, storeToRefs, usePinia, acceptHMRUpdate, all stores
→ Load `references/ssr-and-nuxt.md` for: Complete SSR patterns, Nuxt configuration, server-side data fetching, SSR pitfalls, debugging
Testing
Load `references/testing-guide.md` for complete testing guide.
Testing Quick Start
Component Testing
→ Load `references/testing-guide.md` for: Complete test patterns, stubbing actions, mocking getters, async testing, SSR testing
Hot Module Replacement (HMR)
Vite Setup
Webpack Setup
Benefits:
- Edit stores without full page reload
- Preserve application state during development
- Faster development iteration
Options API Usage
For projects still using Options API, load complete mapper documentation.
→ Load `references/state-getters-actions.md` for: Complete Options API integration, all mappers (mapStores, mapState, mapWritableState, mapActions)
Migrating from Vuex
Load `references/vuex-migration.md` for complete migration guide.
Quick Conversion Overview
Key Changes:
- Remove
namespaced(automatic via store ID) - Eliminate
mutations(direct state mutation) - Replace
commit()with direct mutations - Replace
rootState/rootGetterswith store imports - Use
store.$reset()instead of custom clear mutations
Directory: store/modules/ → stores/ (each module = separate store)
→ Load `references/vuex-migration.md` for: Complete conversion steps, component migration, checklist, gradual migration strategy
Critical Rules
Always Do
✅ Define all state properties in state() or return them from setup stores ✅ Use storeToRefs() when destructuring state/getters in components ✅ Call app.use(pinia) BEFORE mounting the app ✅ Return all state from setup stores (private state breaks SSR/DevTools) ✅ Call useStore() inside functions/callbacks when used outside components ✅ Use acceptHMRUpdate() for development HMR support ✅ Type return values when getters use this to access other getters ✅ Use devalue for SSR state serialization (prevents XSS) ✅ Hydrate state BEFORE calling any useStore() on the client (SSR) ✅ Call all useStore() BEFORE any await in async actions (SSR)
Never Do
❌ Add state properties dynamically after store creation ❌ Destructure store directly without storeToRefs() (loses reactivity) ❌ Use arrow functions for actions (need this context) ❌ Return private state in setup stores (breaks SSR/DevTools/plugins) ❌ Call useStore() at module top-level (before Pinia installed) ❌ Create circular dependencies between stores (both reading each other's state) ❌ Use JSON.stringify() for SSR serialization (vulnerable to XSS) ❌ Call useStore() after await in actions (breaks SSR) ❌ Forget to type getter return values when using this ❌ Skip beforeEach(() => setActivePinia(createPinia())) in unit tests
Known Issues Prevention
This skill prevents 12 documented issues:
Issue #1: Lost Reactivity from Direct Destructuring
Error: State changes don't update in template after destructuring Why It Happens: JavaScript destructuring breaks Vue reactivity Prevention: Always use storeToRefs() for state/getters
Issue #2: Cannot Add State Properties Dynamically
Error: New properties added after store creation aren't reactive Why It Happens: Pinia needs all properties defined upfront for reactivity Prevention: Declare all properties in state(), even if initially undefined
Issue #3: Store Not Found Before Pinia Install
Error: getActivePinia() returns undefined Why It Happens: Calling useStore() before app.use(pinia) Prevention: Call app.use(pinia) before mounting or accessing stores
Issue #4: Setup Store Private State Breaks SSR
Error: State not serialized/hydrated correctly in SSR Why It Happens: Properties not returned from setup aren't tracked Prevention: Return ALL state properties from setup stores
Issue #5: Getters with this Don't Infer Types
Error: TypeScript can't infer return type when getter uses this Source: Known TypeScript limitation with Pinia Prevention: Explicitly type return value: getterName(): ReturnType { ... }
Issue #6: Options API Store Suffix Confusion
Error: Can't find this.counterStore in component Why It Happens: mapStores() automatically adds 'Store' suffix Prevention: Use store name + 'Store' or call setMapStoreSuffix()
Issue #7: Actions Called After await Break SSR
Error: Wrong Pinia instance used in SSR, causing state pollution Why It Happens: await changes execution context in async functions Prevention: Call all useStore() before any await statements
Issue #8: Circular Store Dependencies Crash App
Error: Maximum call stack exceeded Why It Happens: Both stores read each other's state during initialization Prevention: Use getters/actions for cross-store access, not setup-time reads
Issue #9: XSS Vulnerability in SSR State Serialization
Error: User input in state can execute malicious scripts Why It Happens: JSON.stringify() doesn't escape executable code Prevention: Use devalue library for safe serialization
Issue #10: HMR Doesn't Work in Development
Error: Changes to store require full page reload Why It Happens: Vite/webpack HMR not configured for store Prevention: Add acceptHMRUpdate() block to each store file
Issue #11: Composables Return Functions Break Option Stores
Error: Store state contains non-serializable functions Why It Happens: Option stores state() can only return writable refs Prevention: Use setup stores for complex composables, or extract only writable state
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 93 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingplugins/pinia-v3/skills/pinia-v3/SKILL.md
Popularity
- Repository stars
- 216
- Repository forks
- 31
- 7-day trend score
- 27
Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 23 Mar 2026, 7 months ago.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/secondsky/claude-skills/pinia-v3)