Skip to content
Development
Skill

/pinia-colada

Pinia Colada data fetching for Vue/Nuxt with useQuery, useMutation. Use for async state, query cache, SSR, or encountering invalidation, hydration, TanStack Vue Query migration errors.

From plugin
secondsky-claude-skills
219183 skills42 agents62 commands2 MCP
Install
$ npx -y skills add secondsky/claude-skills --skill pinia-colada --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/pinia-colada

Context preview

The summary Claude sees to decide when to auto-load this skill.

Pinia Colada data fetching for Vue/Nuxt with useQuery, useMutation. Use for async state, query cache, SSR, or encountering invalidation, hydration, TanStack Vue Query migration errors.

SKILL.md

pinia-colada.SKILL.md
name: pinia-colada
description: "Pinia Colada data fetching for Vue/Nuxt with useQuery, useMutation. Use for async state, query cache, SSR, or encountering invalidation, hydration, TanStack Vue Query migration errors."
license: MIT
metadata:
  version: "2.0.0"
  pinia_colada_version: "0.17.9"
  pinia_version: "3.0.4"
  vue_version: "3.5.25"
  last_verified: "2025-11-28"
  production_tested: true
  token_savings: "~65%"
  errors_prevented: 12
  references_included: 4
  keywords:
    - Pinia Colada
    - "@pinia/colada"
    - useQuery
    - useMutation
    - useQueryCache
    - data fetching
    - async state
    - Vue 3
    - Nuxt
    - Pinia
    - server state
    - caching
    - staleTime
    - gcTime
    - query invalidation
    - prefetching
    - optimistic updates
    - mutations
    - query keys
    - paginated queries
    - SSR
    - server-side rendering
    - Nuxt module
    - "@pinia/colada-nuxt"
    - query cache
    - auto-refetch
    - cache invalidation
    - request deduplication
    - loading states
    - error handling
    - onSettled
    - onSuccess
    - onError
    - defineColadaLoader

Pinia Colada - Smart Data Fetching for Vue

**Status**: Production Ready ✅ | **Last Updated**: 2025-11-28 **Latest Version**: @pinia/colada@0.17.9 | **Dependencies**: Vue 3.5.17+, Pinia 2.2.6+ or 3.0+

---

Quick Start (5 Minutes)

1. Install Dependencies

**For Vue Projects:**

bun add @pinia/colada pinia  # preferred
# or: bun add @pinia/colada pinia

**For Nuxt Projects:**

bun add @pinia/nuxt @pinia/colada-nuxt  # install both Pinia and Pinia Colada modules
# or: bun add @pinia/nuxt @pinia/colada-nuxt

**Why this matters:**

  • Pinia Colada requires Pinia 2.2.6+ or 3.0+ as peer dependency
  • Nuxt module handles SSR serialization automatically
  • Vue 3.5.17+ required for optimal reactivity

2. Set Up Pinia Colada Plugin

**For Vue Projects:**

// src/main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { PiniaColada } from '@pinia/colada'
import App from './App.vue'

const app = createApp(App)
const pinia = createPinia()

app.use(pinia)
app.use(PiniaColada, {
  // Optional: Configure defaults
  query: {
    staleTime: 5000,        // 5 seconds
    gcTime: 5 * 60 * 1000,  // 5 minutes (garbage collection)
    refetchOnMount: true,
    refetchOnWindowFocus: false,
  },
})

app.mount('#app')

**For Nuxt Projects:**

// nuxt.config.ts
export default defineNuxtConfig({
  modules: [
    '@pinia/nuxt',           // Must be before @pinia/colada-nuxt
    '@pinia/colada-nuxt',
  ],

  // Optional: Configure Pinia Colada
  piniaColada: {
    query: {
      staleTime: 5000,
      gcTime: 5 * 60 * 1000,
    },
  },
})

**CRITICAL:**

  • For Nuxt: `@pinia/nuxt` must be listed before `@pinia/colada-nuxt`
  • Plugin must be registered after Pinia instance
  • Configuration is optional - sensible defaults provided

3. Create First Query

<script setup lang="ts">
import { useQuery } from '@pinia/colada'

interface Todo {
  id: number
  title: string
  completed: boolean
}

async function fetchTodos(): Promise<Todo[]> {
  const response = await fetch('/api/todos')
  if (!response.ok) {
    throw new Error('Failed to fetch todos')
  }
  return response.json()
}

const {
  data,       // Ref<Todo[] | undefined>
  isPending,  // Ref<boolean> - initial loading
  isLoading,  // Ref<boolean> - any loading (including refetch)
  error,      // Ref<Error | null>
  refresh,    // () => Promise<void> - manual refetch
} = useQuery({
  key: ['todos'],
  query: fetchTodos,
})
</script>

<template>
  <div>
    <div v-if="isPending">Loading todos...</div>
    <div v-else-if="error">Error: {{ error.message }}</div>
    <ul v-else-if="data">
      <li v-for="todo in data" :key="todo.id">
        {{ todo.title }}
      </li>
    </ul>
  </div>
</template>

**CRITICAL:**

  • Query `key` must be an array (or getter returning array) for consistent caching
  • Query `query` is the async function that fetches data
  • Throw errors in query function for proper error handling
  • `isPending` is `true` only on initial load, `isLoading` includes refetches

4. Create First Mutation

<script setup lang="ts">
import { useMutation, useQueryCache } from '@pinia/colada'

interface NewTodo {
  title: string
}

async function createTodo(newTodo: NewTodo) {
  const response = await fetch('/api/todos', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(newTodo),
  })
  if (!response.ok) throw new Error('Failed to create todo')
  return response.json()
}

const queryCache = useQueryCache()

const {
  mutate,        // (variables: NewTodo) => Promise<void>
  mutateAsync,   // (variables: NewTodo) => Promise<Result>
  isPending,     // Ref<boolean>
  error,         // Ref<Error | null>
  data,          // Ref<Result | undefined>
} = useMutation({
  mutation: createTodo,

  // Invalidate todos query after mutation succeeds
  async onSettled({ id }) {
    await queryCache.invalidateQueries({ key: ['todos'] })
  },
})

function handleAddTodo(title: string) {
  mutate({ title })
}
</script>

<template>
  <form @submit.prevent="handleAddTodo(newTitle)">
    <input v-model="newTitle" required />
    <button type="submit" :disabled="isPending">
      {{ isPending ? 'Adding...' : 'Add Todo' }}
    </button>
    <div v-if="error">Error: {{ error.message }}</div>
  </form>
</template>

**Why this works:**

  • `onSettled` runs after success or error, perfect for invalidation
  • `invalidateQueries` marks matching queries as stale and refetches active ones
  • `mutate` is fire-and-forget, `mutateAsync` returns Promise for await
  • Mutations don't cache by default (correct behavior for writes)

---

Critical Rules

Always Do

✅ Include all variables used in query function in the key ✅ Throw errors in query/mutation functions for proper error handling ✅ Use `useQueryCache()` for invalidation

Read more
Ships withsecondsky-claude-skills

145 production-ready skills for Claude Code CLI 🔌 Platform / Harness Support These plugins ship as Claude Code marketplace plugins (.claude-plugin/ manifests) and Codex CLI plugins (.codex-plugin/ manifests).

Get the whole plugin

Other skills on secondsky-claude-skills.