Developing Pinia Stores
When to use this skill
Use this skill when you need to:
- Create new Pinia stores for state management
- Define store state, getters, and actions
- Compose multiple stores together
- Integrate stores with Vue components
- Handle async operations in stores
- Refactor stores for better type safety or structure
Store File Structure
storeName.ts: Store definition with state, getters, and actions
- Place stores in
stores/ directory (e.g., stores/user.ts, stores/cart.ts)
- Use
use<Name>Store naming convention (e.g., useUserStore, useCartStore)
Instructions
Creating a New Store
Follow these steps to create a new Pinia store:
Create store file: stores/storeName.ts
Define the store using Setup Store pattern:
- Import
defineStore from Pinia
- Import
ref, computed from Vue
- Define state as
ref() values
- Define getters as
computed() properties
- Define actions as plain functions
- Return all public state, getters, and actions
- See setup-stores.md for patterns
Add TypeScript types:
- Type all state refs explicitly
- Let TypeScript infer computed types when possible
- Type action parameters and return values
- See typescript.md for patterns
Handle async operations (if needed):
- Add loading/error state refs
- Use try/catch/finally in async actions
- Clean up state appropriately
Modifying an Existing Store
Understand current state:
- Review existing state, getters, and actions
- Identify dependencies on other stores
Make changes:
- Add/modify state refs as needed
- Update getters if derived state changes
- Update actions for new behavior
- Ensure all new exports are returned
Update consumers:
- Check components using the store
- Update destructuring if new state/actions added
- Verify reactivity is preserved
Using Stores in Components
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter'
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// Destructure reactive state/getters with storeToRefs
const { count, doubleCount } = storeToRefs(store)
// Actions can be destructured directly
const { increment, reset } = store
</script>
Quality Checklist
Before completing work on any store, verify:
Best Practices
Naming:
- Store IDs: lowercase with hyphens (
'user-settings')
- Store functions:
use<Name>Store pattern (useUserSettingsStore)
- State: descriptive nouns (
items, currentUser, isLoading)
- Getters: descriptive, often prefixed with
is/has/get (isLoggedIn, totalItems)
- Actions: verbs describing the action (
fetchUser, addItem, reset)
State Management:
- Keep stores focused on a single domain
- Prefer multiple small stores over one large store
- Use
shallowRef() for large objects that don't need deep reactivity
- Initialize state with sensible defaults
Composition:
- Access other stores inside actions/getters, not at setup level
- Avoid circular dependencies between stores
- Use composables for shared logic
- See composables.md for patterns
Type Safety:
- Always type state refs explicitly
- Export store return type for consumers
- Avoid
any and unknown types
- See typescript.md for patterns
Note:
- For detailed patterns and examples, consult the reference documentation in the
references/ directory.
- Starter template is available in the
assets/ directory.
1---2name: pinia3description: Create and maintain Pinia stores using Setup Stores pattern with TypeScript. Use when creating state management stores, defining store state/getters/actions, composing stores, or integrating with Vue components. Handles store architecture, type safety, and reactive state patterns.4license: Apache-2.05---67# Developing Pinia Stores89## When to use this skill1011Use this skill when you need to:1213- Create new Pinia stores for state management14- Define store state, getters, and actions15- Compose multiple stores together16- Integrate stores with Vue components17- Handle async operations in stores18- Refactor stores for better type safety or structure1920## Store File Structure2122- `storeName.ts`: Store definition with state, getters, and actions23- Place stores in `stores/` directory (e.g., `stores/user.ts`, `stores/cart.ts`)24- Use `use<Name>Store` naming convention (e.g., `useUserStore`, `useCartStore`)2526## Instructions2728### Creating a New Store2930Follow these steps to create a new Pinia store:31321. **Create store file**: `stores/storeName.ts`33342. **Define the store** using Setup Store pattern:35 - Import `defineStore` from Pinia36 - Import `ref`, `computed` from Vue37 - Define state as `ref()` values38 - Define getters as `computed()` properties39 - Define actions as plain functions40 - Return all public state, getters, and actions41 - See [setup-stores.md](references/setup-stores.md) for patterns42433. **Add TypeScript types**:44 - Type all state refs explicitly45 - Let TypeScript infer computed types when possible46 - Type action parameters and return values47 - See [typescript.md](references/typescript.md) for patterns48494. **Handle async operations** (if needed):50 - Add loading/error state refs51 - Use try/catch/finally in async actions52 - Clean up state appropriately5354### Modifying an Existing Store55561. **Understand current state**:57 - Review existing state, getters, and actions58 - Identify dependencies on other stores59602. **Make changes**:61 - Add/modify state refs as needed62 - Update getters if derived state changes63 - Update actions for new behavior64 - Ensure all new exports are returned65663. **Update consumers**:67 - Check components using the store68 - Update destructuring if new state/actions added69 - Verify reactivity is preserved7071### Using Stores in Components7273```vue74<script setup lang="ts">75import { useCounterStore } from '@/stores/counter'76import { storeToRefs } from 'pinia'7778const store = useCounterStore()7980// Destructure reactive state/getters with storeToRefs81const { count, doubleCount } = storeToRefs(store)8283// Actions can be destructured directly84const { increment, reset } = store85</script>86```8788### Quality Checklist8990Before completing work on any store, verify:9192- [ ] Store uses Setup Store pattern (not Options API)93- [ ] All state is typed explicitly94- [ ] Getters use `computed()` for reactivity95- [ ] Async actions have loading/error handling96- [ ] No circular dependencies between stores97- [ ] Store is properly exported and named (`use<Name>Store`)98- [ ] Components use `storeToRefs()` for destructuring state99100## Best Practices101102**Naming**:103104- Store IDs: lowercase with hyphens (`'user-settings'`)105- Store functions: `use<Name>Store` pattern (`useUserSettingsStore`)106- State: descriptive nouns (`items`, `currentUser`, `isLoading`)107- Getters: descriptive, often prefixed with `is`/`has`/`get` (`isLoggedIn`, `totalItems`)108- Actions: verbs describing the action (`fetchUser`, `addItem`, `reset`)109110**State Management**:111112- Keep stores focused on a single domain113- Prefer multiple small stores over one large store114- Use `shallowRef()` for large objects that don't need deep reactivity115- Initialize state with sensible defaults116117**Composition**:118119- Access other stores inside actions/getters, not at setup level120- Avoid circular dependencies between stores121- Use composables for shared logic122- See [composables.md](references/composables.md) for patterns123124**Type Safety**:125126- Always type state refs explicitly127- Export store return type for consumers128- Avoid `any` and `unknown` types129- See [typescript.md](references/typescript.md) for patterns130131---132133**Note**:134135- For detailed patterns and examples, consult the reference documentation in the `references/` directory.136- Starter template is available in the `assets/` directory.