skills/vue/SKILL.md
Use when editing Vue projects, .vue files, vue.config.js, Vue 3 components, Composition API, <script setup>, SFC state, deployment workflows, or Vue CI configuration.
npx skillsauth add cofin/flow vueInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';
interface Props {
title: string;
items: Item[];
}
const props = defineProps<Props>();
const emit = defineEmits<{
select: [item: Item];
}>();
const selected = ref<Item | null>(null);
const count = computed(() => props.items.length);
function handleSelect(item: Item) {
selected.value = item;
emit('select', item);
}
onMounted(() => {
console.log('Component mounted');
});
</script>
<template>
<div>
<h2>{{ title }} ({{ count }})</h2>
<ul>
<li
v-for="item in items"
:key="item.id"
@click="handleSelect(item)"
>
{{ item.name }}
</li>
</ul>
</div>
</template>
</example>
// composables/useFetch.ts
import { ref, watchEffect, type Ref } from 'vue';
export function useFetch<T>(url: Ref<string> | string) {
const data = ref<T | null>(null) as Ref<T | null>;
const loading = ref(true);
const error = ref<Error | null>(null);
watchEffect(async () => {
loading.value = true;
error.value = null;
try {
const urlValue = typeof url === 'string' ? url : url.value;
const res = await fetch(urlValue);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
data.value = await res.json();
} catch (e) {
error.value = e instanceof Error ? e : new Error(String(e));
} finally {
loading.value = false;
}
});
return { data, loading, error };
}
</example>
// context/theme.ts
import { provide, inject, ref, type InjectionKey, type Ref } from 'vue';
type Theme = 'light' | 'dark';
const ThemeKey: InjectionKey<{
theme: Ref<Theme>;
toggle: () => void;
}> = Symbol('theme');
export function provideTheme() {
const theme = ref<Theme>('light');
const toggle = () => {
theme.value = theme.value === 'light' ? 'dark' : 'light';
};
provide(ThemeKey, { theme, toggle });
}
export function useTheme() {
const context = inject(ThemeKey);
if (!context) throw new Error('useTheme requires ThemeProvider');
return context;
}
</example>
<script setup lang="ts">
const model = defineModel<string>({ required: true });
// Or with options
const count = defineModel<number>('count', { default: 0 });
</script>
<template>
<input v-model="model" />
</template>
</example>
import { defineAsyncComponent } from 'vue';
const AsyncModal = defineAsyncComponent({
loader: () => import('./Modal.vue'),
loadingComponent: LoadingSpinner,
delay: 200,
errorComponent: ErrorDisplay,
});
</example>
</workflow>
<script setup> for cleaner syntaxdefineProps<T>() and defineEmits<T>()shallowRef for large objects that don't need deep reactivityVue applications are built into static assets using Vite.
vite build
Deploy to static runners or reverse proxies. For Inertia apps, bundle assets inside the backend build directory for joint deployment.
Example GitHub Actions workflow for building:
name: Vue CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- run: npm ci
- run: npm run build
</example>
<script setup> with TypeScript -- This is the modern standard for Vue 3; provides better IDE support and less boilerplate.emit to notify the parent of changes or use computed with a setter.use* functions to keep components focused on UI.defineProps and defineEmits macros -- These are compiler macros; do not import them. Use the type-based declaration for best DX.ref for DOM elements only when necessary; prefer Vue's declarative directives (v-bind, v-if, v-for).
</guardrails>
<script setup lang="ts">defineProps<T>())v-for elements have a unique and stable :keydocument.querySelector) is used where Vue directives suffice
</validation>
development
Use when tracing execution paths, mapping dependencies, understanding unfamiliar code, following data flow, investigating end-to-end behavior, debugging call chains, or deciding which files to read next.
development
Use when reviewing authentication, authorization, user input, secrets, API keys, database queries, file uploads, session management, external API calls, OWASP risks, or data handling attack surface.
testing
Use when analyzing tradeoffs, comparing approaches, weighing options, assessing risks, stress-testing conclusions, identifying blind spots, or applying multiple viewpoints to a decision.
development
Use when reviewing hot paths, slow code, database queries, N+1 risks, memory usage, loops, I/O, caching strategy, concurrency, latency-sensitive paths, or resource efficiency.