/web-framework-vue-composition-api
Vue 3 Composition API patterns, reactivity primitives, composables, lifecycle hooks
$ npx -y skills add agents-inc/skills --skill web-framework-vue-composition-api --agent claude-codeHow 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.
- You can call itInvoke it directly when you want it.
- Slash command
/web-framework-vue-composition-api
Context preview
The summary Claude sees to decide when to auto-load this skill.
Vue 3 Composition API patterns, reactivity primitives, composables, lifecycle hooks
SKILL.md
web-framework-vue-composition-api.SKILL.mdname: web-framework-vue-composition-api
description: Vue 3 Composition API patterns, reactivity primitives, composables, lifecycle hooks
Vue 3 Composition API
> **Quick Guide:** Use `<script setup>` for all components. `ref()` for primitives, `reactive()` for objects. Extract reusable logic into composables (`use*` functions). Clean up side effects in `onUnmounted`. Use `defineModel()` for v-model (3.4+), `useTemplateRef()` for DOM refs (3.5+), `onWatcherCleanup()` to cancel stale async work (3.5+). Destructured props require getter wrappers in `watch()`.
---
<critical_requirements>
CRITICAL: Before Using This Skill
> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)
**(You MUST use `<script setup>` syntax for all new Vue components)**
**(You MUST clean up all side effects (timers, listeners, subscriptions) in `onUnmounted`)**
**(You MUST use `ref()` for primitives and `reactive()` for objects - access ref values via `.value`)**
**(You MUST prefix all composable functions with `use` following Vue conventions)**
**(You MUST wrap destructured props in a getter for `watch()` - `watch(() => count, ...)` not `watch(count, ...)`)**
</critical_requirements>
---
**Auto-detection:** Vue 3 Composition API, script setup, ref, reactive, computed, watch, watchEffect, composables, onMounted, onUnmounted, defineProps, defineEmits, defineExpose, defineModel, useTemplateRef, useId, onWatcherCleanup, provide, inject, Suspense
**When to use:**
- Building Vue 3 components using Composition API
- Creating reusable composables (use\* functions)
- Managing reactive state with ref/reactive
- Handling component lifecycle and side effects
- TypeScript integration with Vue components
**Key patterns covered:**
- Script setup syntax and compiler macros (defineProps, defineEmits, defineExpose)
- Reactivity primitives (ref, reactive, computed, watch, watchEffect)
- Composables pattern for logic reuse
- defineModel() for v-model binding (Vue 3.4+)
- useTemplateRef(), useId(), onWatcherCleanup() (Vue 3.5+)
- Reactive props destructure with getter requirement (Vue 3.5+)
- Provide/Inject for dependency injection
- Async components and Suspense
**When NOT to use:**
- Components that don't benefit from logic extraction
- When team has no Composition API experience (consider gradual adoption)
---
<philosophy>
Philosophy
The Composition API enables organizing code by **logical concern** rather than by option type (data, methods, computed). This makes complex components more maintainable and enables powerful logic reuse through composables.
**Core principles:**
1. **Composition over configuration** - Group related logic together instead of splitting across options 2. **Explicit reactivity** - State is explicitly reactive via `ref()` and `reactive()` 3. **Logic reuse via composables** - Extract and share stateful logic between components 4. **TypeScript-first** - Types flow naturally without excessive annotations
</philosophy>
---
<patterns>
Core Patterns
Pattern 1: Script Setup with Props and Emits
All variables/functions in `<script setup>` are automatically available in the template. Use TypeScript generics with `defineProps` and `defineEmits` for type-safe interfaces.
<script setup lang="ts">
import { ref, computed } from "vue";
const props = defineProps<{
userId: string;
initialCount?: number;
}>();
const emit = defineEmits<{
update: [value: number];
submit: [];
}>();
const count = ref(props.initialCount ?? 0);
const doubleCount = computed(() => count.value * 2);
function increment() {
count.value++;
emit("update", count.value);
}
</script>**Why good:** No explicit return needed, TypeScript types flow naturally, named tuple emit syntax (Vue 3.3+) self-documents payloads
See [examples/core.md](examples/core.md) for a complete component with loading/error handling.
---
Pattern 2: Reactivity - ref vs reactive
`ref()` for primitives and reassignable values, `reactive()` for objects with nested properties. Access ref values via `.value` in script; templates unwrap automatically.
const count = ref(0); // Primitive -> ref
count.value++; // .value in script
const state = reactive({
// Nested object -> reactive
user: null as User | null,
settings: { theme: "light" },
});
state.settings.theme = "dark"; // Direct access, no .value**Gotcha:** Destructuring `reactive()` loses reactivity - use `toRefs(state)` if you need to destructure.
See [examples/reactivity.md](examples/reactivity.md) for ref/reactive/computed patterns and anti-patterns.
---
Pattern 3: Watch and WatchEffect
**Skip if using Nuxt — use useFetch or useAsyncData instead.**
`watch()` for explicit sources with access to old values. `watchEffect()` for automatic dependency tracking that runs immediately. Use `onWatcherCleanup()` (Vue 3.5+) to cancel stale async work.
// watch: explicit source, access to old value
watch(searchQuery, async (newQuery, oldQuery) => {
/* ... */
});
// watchEffect: auto-tracks dependencies, runs immediately
watchEffect(async () => {
if (userId.value) userData.value = await fetchUser(userId.value);
});
// Cleanup: cancel stale requests (Vue 3.5+)
watch(searchQuery, async (query) => {
const controller = new AbortController();
onWatcherCleanup(() => controller.abort());
const res = await fetch(`/api/search?q=${query}`, {
signal: controller.signal,
});
});**Gotcha:** Watch reactive object properties with a getter: `watch(() => state.count, ...)` not `watch(state.count, ...)`.
See [examples/vue-3-5-features.md](examples/vue-3-5-features.md) for complete onWatcherCleanup patterns.
---
Pattern 4: Lifecycle and Cleanup
Always pair `onMounted` setup with `onUnmounted` cleanup. Timers, listeners, observers, WebSockets - anything opened must be closed.
const POLL_INTERVAL_MS = 5000;
l
Read more
name: web-framework-vue-composition-api description: Vue 3 Composition API patterns, reactivity primitives, composables, lifecycle hooks
Vue 3 Composition API
> **Quick Guide:** Use `<script setup>` for all components. `ref()` for primitives, `reactive()` for objects. Extract reusable logic into composables (`use*` functions). Clean up side effects in `onUnmounted`. Use `defineModel()` for v-model (3.4+), `useTemplateRef()` for DOM refs (3.5+), `onWatcherCleanup()` to cancel stale async work (3.5+). Destructured props require getter wrappers in `watch()`.
---
<critical_requirements>
CRITICAL: Before Using This Skill
> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)
**(You MUST use `<script setup>` syntax for all new Vue components)**
**(You MUST clean up all side effects (timers, listeners, subscriptions) in `onUnmounted`)**
**(You MUST use `ref()` for primitives and `reactive()` for objects - access ref values via `.value`)**
**(You MUST prefix all composable functions with `use` following Vue conventions)**
**(You MUST wrap destructured props in a getter for `watch()` - `watch(() => count, ...)` not `watch(count, ...)`)**
</critical_requirements>
---
**Auto-detection:** Vue 3 Composition API, script setup, ref, reactive, computed, watch, watchEffect, composables, onMounted, onUnmounted, defineProps, defineEmits, defineExpose, defineModel, useTemplateRef, useId, onWatcherCleanup, provide, inject, Suspense
**When to use:**
- Building Vue 3 components using Composition API
- Creating reusable composables (use\* functions)
- Managing reactive state with ref/reactive
- Handling component lifecycle and side effects
- TypeScript integration with Vue components
**Key patterns covered:**
- Script setup syntax and compiler macros (defineProps, defineEmits, defineExpose)
- Reactivity primitives (ref, reactive, computed, watch, watchEffect)
- Composables pattern for logic reuse
- defineModel() for v-model binding (Vue 3.4+)
- useTemplateRef(), useId(), onWatcherCleanup() (Vue 3.5+)
- Reactive props destructure with getter requirement (Vue 3.5+)
- Provide/Inject for dependency injection
- Async components and Suspense
**When NOT to use:**
- Components that don't benefit from logic extraction
- When team has no Composition API experience (consider gradual adoption)
---
<philosophy>
Philosophy
The Composition API enables organizing code by **logical concern** rather than by option type (data, methods, computed). This makes complex components more maintainable and enables powerful logic reuse through composables.
**Core principles:**
1. **Composition over configuration** - Group related logic together instead of splitting across options 2. **Explicit reactivity** - State is explicitly reactive via `ref()` and `reactive()` 3. **Logic reuse via composables** - Extract and share stateful logic between components 4. **TypeScript-first** - Types flow naturally without excessive annotations
</philosophy>
---
<patterns>
Core Patterns
Pattern 1: Script Setup with Props and Emits
All variables/functions in `<script setup>` are automatically available in the template. Use TypeScript generics with `defineProps` and `defineEmits` for type-safe interfaces.
<script setup lang="ts">
import { ref, computed } from "vue";
const props = defineProps<{
userId: string;
initialCount?: number;
}>();
const emit = defineEmits<{
update: [value: number];
submit: [];
}>();
const count = ref(props.initialCount ?? 0);
const doubleCount = computed(() => count.value * 2);
function increment() {
count.value++;
emit("update", count.value);
}
</script>**Why good:** No explicit return needed, TypeScript types flow naturally, named tuple emit syntax (Vue 3.3+) self-documents payloads
See [examples/core.md](examples/core.md) for a complete component with loading/error handling.
---
Pattern 2: Reactivity - ref vs reactive
`ref()` for primitives and reassignable values, `reactive()` for objects with nested properties. Access ref values via `.value` in script; templates unwrap automatically.
const count = ref(0); // Primitive -> ref
count.value++; // .value in script
const state = reactive({
// Nested object -> reactive
user: null as User | null,
settings: { theme: "light" },
});
state.settings.theme = "dark"; // Direct access, no .value**Gotcha:** Destructuring `reactive()` loses reactivity - use `toRefs(state)` if you need to destructure.
See [examples/reactivity.md](examples/reactivity.md) for ref/reactive/computed patterns and anti-patterns.
---
Pattern 3: Watch and WatchEffect
**Skip if using Nuxt — use useFetch or useAsyncData instead.**
`watch()` for explicit sources with access to old values. `watchEffect()` for automatic dependency tracking that runs immediately. Use `onWatcherCleanup()` (Vue 3.5+) to cancel stale async work.
// watch: explicit source, access to old value
watch(searchQuery, async (newQuery, oldQuery) => {
/* ... */
});
// watchEffect: auto-tracks dependencies, runs immediately
watchEffect(async () => {
if (userId.value) userData.value = await fetchUser(userId.value);
});
// Cleanup: cancel stale requests (Vue 3.5+)
watch(searchQuery, async (query) => {
const controller = new AbortController();
onWatcherCleanup(() => controller.abort());
const res = await fetch(`/api/search?q=${query}`, {
signal: controller.signal,
});
});**Gotcha:** Watch reactive object properties with a getter: `watch(() => state.count, ...)` not `watch(state.count, ...)`.
See [examples/vue-3-5-features.md](examples/vue-3-5-features.md) for complete onWatcherCleanup patterns.
---
Pattern 4: Lifecycle and Cleanup
Always pair `onMounted` setup with `onUnmounted` cleanup. Timers, listeners, observers, WebSockets - anything opened must be closed.
const POLL_INTERVAL_MS = 5000; l
Showing the first part of this file.
The official skills marketplace for Agents Inc. 150+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?
Repo: agents-inc/skills
Other skills on agents-inc-skills.
- /ai-infrastructure-huggingface-inference
Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation, audio transcription, translation, summarization, and Inference Endpoints
Open skill - /ai-infrastructure-litellm
LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking, virtual keys, and production deployment
Open skill - /ai-infrastructure-modal
Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client patterns
Open skill - /ai-infrastructure-ollama
Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and OpenAI-compatible endpoint
Open skill - /ai-infrastructure-replicate
Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning, deployments, and training
Open skill - /ai-infrastructure-together-ai
Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling, embeddings, image generation, fine-tuning, and OpenAI-compatible endpoints
Open skill

