> pinia
You are an expert in Pinia, the official state management library for Vue.js. You help developers build Vue applications with type-safe stores, Composition API support, getters (computed), actions (sync and async), plugins, SSR compatibility, and Vue DevTools integration — replacing Vuex with a simpler, fully typed, modular store system.
curl "https://skillshub.wtf/TerminalSkills/skills/pinia?format=md"Pinia — Official Vue.js State Management
You are an expert in Pinia, the official state management library for Vue.js. You help developers build Vue applications with type-safe stores, Composition API support, getters (computed), actions (sync and async), plugins, SSR compatibility, and Vue DevTools integration — replacing Vuex with a simpler, fully typed, modular store system.
Core Capabilities
Store Definition
// stores/auth.ts
import { defineStore } from "pinia";
import { ref, computed } from "vue";
// Setup Store (Composition API style)
export const useAuthStore = defineStore("auth", () => {
const user = ref<User | null>(null);
const token = ref<string | null>(localStorage.getItem("token"));
const isLoading = ref(false);
// Getters (computed)
const isAuthenticated = computed(() => !!token.value);
const isAdmin = computed(() => user.value?.role === "admin");
// Actions
async function login(email: string, password: string) {
isLoading.value = true;
try {
const response = await api.post("/auth/login", { email, password });
token.value = response.data.token;
user.value = response.data.user;
localStorage.setItem("token", token.value!);
} finally {
isLoading.value = false;
}
}
function logout() {
token.value = null;
user.value = null;
localStorage.removeItem("token");
}
async function fetchProfile() {
if (!token.value) return;
user.value = await api.get("/auth/profile");
}
return { user, token, isLoading, isAuthenticated, isAdmin, login, logout, fetchProfile };
});
// Option Store style (familiar to Vuex users)
export const useCartStore = defineStore("cart", {
state: () => ({
items: [] as CartItem[],
}),
getters: {
total: (state) => state.items.reduce((sum, i) => sum + i.price * i.qty, 0),
itemCount: (state) => state.items.reduce((sum, i) => sum + i.qty, 0),
},
actions: {
addItem(product: Product) {
const existing = this.items.find(i => i.id === product.id);
if (existing) existing.qty++;
else this.items.push({ ...product, qty: 1 });
},
removeItem(id: string) {
this.items = this.items.filter(i => i.id !== id);
},
async checkout() {
await api.post("/orders", { items: this.items });
this.items = [];
},
},
});
Usage in Components
<script setup lang="ts">
import { useAuthStore } from "@/stores/auth";
import { useCartStore } from "@/stores/cart";
import { storeToRefs } from "pinia";
const auth = useAuthStore();
const cart = useCartStore();
// storeToRefs preserves reactivity for destructured state/getters
const { user, isAuthenticated } = storeToRefs(auth);
const { total, itemCount } = storeToRefs(cart);
</script>
<template>
<nav>
<span v-if="isAuthenticated">{{ user?.name }}</span>
<button v-else @click="auth.login(email, password)">Login</button>
<span>Cart ({{ itemCount }}): ${{ total.toFixed(2) }}</span>
</nav>
</template>
Installation
npm install pinia
// main.ts
import { createPinia } from "pinia";
app.use(createPinia());
Best Practices
- Setup stores — Prefer Composition API style (
ref,computed); full TypeScript inference without extra types - storeToRefs — Use
storeToRefs(store)when destructuring; plain destructure breaks reactivity - One store per domain — Separate auth, cart, ui stores; avoid a single monolithic store
- Actions for async — Put API calls in actions; components stay clean, logic is reusable and testable
- Getters for derived — Use computed/getters for filtered lists, totals, formatted values; auto-cached
- Plugins — Use plugins for persistence (
pinia-plugin-persistedstate), logging, or shared behaviors - Store composition — Import other stores inside a store:
const auth = useAuthStore(); explicit dependencies - DevTools — Pinia integrates with Vue DevTools; inspect state, time-travel, edit state in real-time
> related_skills --same-repo
> zustand
You are an expert in Zustand, the small, fast, and scalable state management library for React. You help developers manage global state without boilerplate using Zustand's hook-based stores, selectors for performance, middleware (persist, devtools, immer), computed values, and async actions — replacing Redux complexity with a simple, un-opinionated API in under 1KB.
> zoho
Integrate and automate Zoho products. Use when a user asks to work with Zoho CRM, Zoho Books, Zoho Desk, Zoho Projects, Zoho Mail, or Zoho Creator, build custom integrations via Zoho APIs, automate workflows with Deluge scripting, sync data between Zoho apps and external systems, manage leads and deals, automate invoicing, build custom Zoho Creator apps, set up webhooks, or manage Zoho organization settings. Covers Zoho CRM, Books, Desk, Projects, Creator, and cross-product integrations.
> zod
You are an expert in Zod, the TypeScript-first schema declaration and validation library. You help developers define schemas that validate data at runtime AND infer TypeScript types at compile time — eliminating the need to write types and validators separately. Used for API input validation, form validation, environment variables, config files, and any data boundary.
> zipkin
Deploy and configure Zipkin for distributed tracing and request flow visualization. Use when a user needs to set up trace collection, instrument Java/Spring or other services with Zipkin, analyze service dependencies, or configure storage backends for trace data.