Pinia
Anthony FuCommunityCreated by Anthony Fu
- Skill
- Tool integration
- Software development
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
Pinia is the official state management library for Vue, offering an intuitive API for managing application state. It supports both Options and Composition API styles, provides first-class TypeScript support, and includes built-in devtools integration. The library facilitates store creation, state management, and complex logic handling through actions and getters, with specific support for server-side rendering and Nuxt integration.
What it does
- Defines stores using Options or Composition API patterns
- Provides reactive state management with getters and actions
- Supports store-to-store communication and composable integration
- Enables store extensibility through custom plugins
- Facilitates server-side rendering and state hydration
- Supports hot module replacement for development workflows
When to use it
- When implementing centralized state management in Vue applications
- When requiring type-safe store definitions in TypeScript projects
- When building Nuxt applications needing integrated state handling
- When needing to preserve state during development via HMR
- When testing components that rely on shared store state
Advantages
- First-class TypeScript support for type-safe stores
- Seamless integration with Nuxt and server-side rendering
- Flexible store definition styles for different architectural needs
- Built-in support for devtools and hot module replacement
- Extensible architecture via plugin system
Usage examples
- “How do I define a basic store in Pinia?”
- You use the defineStore function to create a store, providing a unique ID and either an object for Options API or a function for Composition API.
- “How can I preserve state during development?”
- You can implement Hot Module Replacement (HMR) by using the acceptHMRUpdate function within your store definition file.
- “How do I use a store inside a Nuxt middleware?”
- You access the store by passing the pinia instance from useNuxtApp to your store function, ensuring it is available in the middleware context.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/antfu/pinia/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip pinia.zip -d .agents/skills
Documentation by Anthony Fu
Pinia
Pinia is the official state management library for Vue, designed to be intuitive and type-safe. It supports both Options API and Composition API styles, with first-class TypeScript support and devtools integration.
The skill is based on Pinia v4.0.3, generated at 2026-09-25.
Core References
| Topic | Description | Reference |
|---|---|---|
| Stores | Defining stores, state, getters, actions, storeToRefs, subscriptions | core-stores |
Features
Extensibility
| Topic | Description | Reference |
|---|---|---|
| Plugins | Extend stores with custom properties, state, and behavior | features-plugins |
Composability
| Topic | Description | Reference |
|---|---|---|
| Composables | Using Vue composables within stores (VueUse, etc.) | features-composables |
| Composing Stores | Store-to-store communication, avoiding circular dependencies | features-composing-stores |
Best Practices
| Topic | Description | Reference |
|---|---|---|
| Testing | Unit testing with @pinia/testing, mocking, stubbing | best-practices-testing |
| Outside Components | Using stores in navigation guards, plugins, middlewares | best-practices-outside-component |
Advanced
| Topic | Description | Reference |
|---|---|---|
| SSR | Server-side rendering, state hydration | advanced-ssr |
| Nuxt | Nuxt integration, auto-imports, SSR best practices | advanced-nuxt |
| HMR | Hot module replacement for development | advanced-hmr |
Key Recommendations
Prefer Setup Stores for complex logic, composables, and watchers
Use
storeToRefs()when destructuring state/getters to preserve reactivityActions can be destructured directly - they're bound to the store
Call stores inside functions not at module scope, especially for SSR
Add HMR support to each store for better development experience
Use
@pinia/testingfor component tests with mocked stores
Files
- ATTRIBUTION.mdAdded by AutoGineer892 B
- GENERATION.md135 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md2.7 KiB
- references/advanced-hmr.md1.4 KiB
- references/advanced-nuxt.md2.6 KiB
- references/advanced-ssr.md2.4 KiB
- references/best-practices-outside-component.md2.2 KiB
- references/best-practices-testing.md4.7 KiB
- references/core-stores.md7.6 KiB
- references/features-composables.md2.7 KiB
- references/features-composing-stores.md2.6 KiB
- references/features-plugins.md3.6 KiB
references/best-practices-testing.md
name: testing description: Unit testing stores and components with @pinia/testing
Testing Stores
Unit Testing Stores
Create a fresh pinia instance for each test:
import { setActivePinia, createPinia } from 'pinia'
import { useCounterStore } from '../src/stores/counter'
describe('Counter Store', () => {
beforeEach(() => {
setActivePinia(createPinia())
})
it('increments', () => {
const counter = useCounterStore()
expect(counter.n).toBe(0)
counter.increment()
expect(counter.n).toBe(1)
})
})With Plugins
import { setActivePinia, createPinia } from 'pinia'
import { createApp } from 'vue'
import { somePlugin } from '../src/stores/plugin'
const app = createApp({})
beforeEach(() => {
const pinia = createPinia().use(somePlugin)
app.use(pinia)
setActivePinia(pinia)
})Testing Components
Install @pinia/testing:
npm i -D @pinia/testingUse createTestingPinia():
import { mount } from '@vue/test-utils'
import { createTestingPinia } from '@pinia/testing'
import { useSomeStore } from '@/stores/myStore'
const wrapper = mount(Counter, {
global: {
plugins: [createTestingPinia()],
},
})
const store = useSomeStore()
// Manipulate state directly
store.name = 'new name'
store.$patch({ name: 'new name' })
// Actions are stubbed by default
store.someAction()
expect(store.someAction).toHaveBeenCalledTimes(1)Initial State
Set initial state for tests:
const wrapper = mount(Counter, {
global: {
plugins: [
createTestingPinia({
initialState: {
counter: { n: 20 }, // Store name → initial state
},
}),
],
},
})Action Stubbing
Stubbing Limitations in Setup Stores
stubActions only replaces actions on the store instance. In a Setup store, an action that calls another action via its closed-over function reference bypasses the stub:
export const useCounterStore = defineStore('counter', () => {
function increment() { /* ... */ }
function incrementTwice() {
increment() // ❌ closed-over reference — stub never used
increment()
}
return { increment, incrementTwice }
})Stubbing affects store.increment() but not the internal calls in incrementTwice(). Options stores don't have this issue — internal this.increment() calls go through the store instance and hit the stub.
To make an internal call stubbable in a Setup store, route it through the store (overkill just for a test — prefer testing the real implementation instead):
function incrementTwice() {
const store = useCounterStore()
store.increment() // ✅ goes through the store, uses the stub
store.increment()
}Execute Real Actions
createTestingPinia({ stubActions: false })Selective Stubbing
// Only stub specific actions
createTestingPinia({
stubActions: ['increment', 'reset'],
})
// Or use a function
createTestingPinia({
stubActions: (actionName, store) => {
if (actionName.startsWith('set')) return true
return false
},
})Mock Action Return Values
import type { Mock } from 'vitest'
// After getting store
store.someAction.mockResolvedValue('mocked value')Mocking Getters
Getters are writable in tests:
const pinia = createTestingPinia()
const counter = useCounterStore(pinia)
counter.double = 3 // Override computed value
// Reset to default behavior
counter.double = undefined
counter.double // Now computed normallyCustom Spy Function
If not using Jest/Vitest with globals:
import { vi } from 'vitest'
createTestingPinia({
createSpy: vi.fn,
})With Sinon:
import sinon from 'sinon'
createTestingPinia({
createSpy: sinon.spy,
})Pinia Plugins in Tests
Pass plugins to createTestingPinia():
import { somePlugin } from '../src/stores/plugin'
createTestingPinia({
stubActions: false,
plugins: [somePlugin],
})Don't use testingPinia.use(MyPlugin) - pass plugins in options.
Type-Safe Mocked Store
import type { Mock } from 'vitest'
import type { Store, StoreDefinition } from 'pinia'
function mockedStore<TStoreDef extends () => unknown>(
useStore: TStoreDef
): TStoreDef extends StoreDefinition<infer Id, infer State, infer Getters, infer Actions>
? Store<Id, State, Record<string, never>, {
[K in keyof Actions]: Actions[K] extends (...args: any[]) => any
? Mock<Actions[K]>
: Actions[K]
}>
: ReturnType<TStoreDef> {
return useStore() as any
}
// Usage
const store = mockedStore(useSomeStore)
store.someAction.mockResolvedValue('value') // Typed!E2E Tests
No special handling needed - Pinia works normally.
<!-- Source references: - https://pinia.vuejs.org/cookbook/testing.html -->
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Anthony Fu
- Publisher
- Anthony Fu (Community)
- Source
- antfu/skills · skills/pinia · commit f63e9ec
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE.md)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Anthony Fu.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download pinia.zip