Back to skills
SKILL.md
Vue Expert
ASecurityUse when building, styling, optimizing, and auditing vue expert components, responsive layouts, design systems, and frontend state.
- 5 stars
- 0 votes
- 0 copies
- 0 views
- Added September 27, 2026
Works with
Security analysis
100/100npx -y skills add Harmitx7/tribunal-kit --skill vue-expert --agent claude-codeAre you the author of Vue Expert?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/harmitx7-vue-expert)---
name: vue-expert
description: "Use when building, styling, optimizing, and auditing vue expert components, responsive layouts, design systems, and frontend state."
version: 6.0.0
last-updated: 2026-09-29
skills:
- baseline-ui
- better-ui
- 60fps-animation
tools: Read, Grep, Glob, Bash, Edit, Write
scripts-binding:
- .agent/scripts/lint_runner.js
- .agent/scripts/verify_all.js
---
# Vue 3.5+ & Nuxt 4 β Dense Reference
## Mandatory Pre-Flight Context Inspection
Before reading, generating, or refactoring code in the `vue-expert` domain, inspect these 5 critical parameters:
1. **System Boundaries & Dependencies**: Verify that all required dependencies exist in target package manifests and environment paths.
2. **Runtime Context & Platform Invariants**: Confirm target platform constraints (Node.js, Browser, Mobile OS, Edge runtime) before applying APIs.
3. **Execution Guardrails**: Identify potential side-effects, state mutations, and unhandled asynchronous exceptions.
4. **Validation & Type Contracts**: Validate input data schemas and strict type constraints across all module interfaces.
5. **Observability & Proof of Execution**: Ensure execution produces tangible verification signals (terminal output, tests, metrics).
## Activation Boundaries
- **Activate when:** Use when building, styling, optimizing, and auditing vue expert components, responsive layouts, design systems, and frontend state.
- **DO NOT activate when:** The task falls outside the `vue-expert` domain or is managed by a different dedicated specialist agent.
## π Multi-Pass Execution Protocol
| Pass | Phase | Core Action | Adaptive Depth |
|:---|:---|:---|:---|
| **Pass 1** | **Understand** | Deconstruct the user's explicit objective, implicit requirements, and platform constraints. | Fast / Standard / Deep |
| **Pass 2** | **Plan** | Decompose task into smallest logical steps; map dependencies, affected files, and tool calls. | Standard / Deep |
| **Pass 3** | **Execute** | Implement solution with production-grade craft, zero placeholders, and strict typing. | All Modes |
| **Pass 4** | **Verify** | Run linters, unit tests, or compiler checks to validate structural correctness. | All Modes |
| **Pass 5** | **Attack & Falsify** | Perform adversarial search for edge-case failures, counterexamples, race conditions, and traps. | Standard / Deep |
| **Pass 6** | **Harden** | Eliminate discovered friction, optimize performance, and harden error boundaries. | Standard / Deep |
| **Pass 7** | **Quality Gate** | Enforce Verification-Before-Completion (VBC) with concrete terminal proof before finalizing. | All Modes |
---
## π οΈ Technical Architecture & Reference Recipes
## Hallucination Traps (Read First)
- β Options API (`data()`, `methods:`, `computed:`) β β
`<script setup lang="ts">`
- β `defineComponent()` with `<script setup>` β β
redundant, skip it
- β `defineModel` in Vue < 3.4 β β
added in 3.4+
- β `ref.value` in template β β
auto-unwrapped in template (no `.value`)
- β `reactive()` for primitives β β
use `ref()` β `reactive()` breaks on reassign
- β `watch(state.count, ...)` (primitive) β β
`watch(() => state.count, ...)`
- β `onBeforeMount` for data fetch β β
use `await` directly in `<script setup>` + `<Suspense>`
- β Pinia `this.$store` β β
`useStore()` from `pinia`
- β `useRoute()` / `useRouter()` outside setup β β
only works inside `<script setup>` or composables
---
## `<script setup>` β The Only Way
```vue
<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue';
// Props
const props = defineProps<{ title: string; count?: number }>();
// With defaults:
const props = withDefaults(defineProps<{ variant?: 'primary' | 'secondary' }>(), {
variant: 'primary',
});
// Emits
const emit = defineEmits<{ update: [value: string]; delete: [id: number] }>();
// v-model (Vue 3.4+)
const modelValue = defineModel<string>(); // default model
const count = defineModel<number>('count'); // named model
// Expose to parent ref
defineExpose({ reset: () => {}, focus: () => {} });
</script>
```
---
## Reactivity
```ts
// ref β for primitives and objects (access via .value in JS, auto-unwrap in template)
const count = ref(0);
count.value++;
// reactive β for objects (loses reactivity on reassign/destructure)
const state = reactive({ name: 'Alice', age: 25 });
// β const { name } = state; // loses reactivity
// β
const name = computed(() => state.name);
// computed β cached, re-runs only when deps change
const doubled = computed(() => count.value * 2);
const fullName = computed({
get: () => `${first.value} ${last.value}`,
set: v => {
[first.value, last.value] = v.split(' ');
},
});
// watch
watch(count, (newVal, oldVal) => {}); // immediate: false by default
watch(() => props.id, fetchUser, { immediate: true });
watchEffect(() => {
console.log(count.value);
}); // auto-tracks deps
```
---
## Composables (Custom Hooks)
```ts
// useCounter.ts
export function useCounter(initial = 0) {
const count = ref(initial);
const increment = () => count.value++;
const reset = () => (count.value = initial);
return { count: readonly(count), increment, reset };
}
// useAsyncData.ts
export function useAsyncData<T>(fn: () => Promise<T>) {
const data = ref<T | null>(null);
const error = ref<Error | null>(null);
const loading = ref(false);
async function execute() {
loading.value = true;
try {
data.value = await fn();
} catch (e) {
error.value = e as Error;
} finally {
loading.value = false;
}
}
execute();
return { data, error, loading, refresh: execute };
}
```
---
## Pinia
```ts
// stores/counter.ts
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', () => {
const count = ref(0); // Setup Store (preferred)
const doubled = computed(() => count.value * 2);
function increment() {
count.value++;
}
return { count, doubled, increment };
});
// Usage in component:
const store = useCounterStore();
// β const { count } = store; // loses reactivity!
// β
const count = storeToRefs(store).count;
import { storeToRefs } from 'pinia';
const { count } = storeToRefs(store);
// Persist plugin:
import { createPinia } from 'pinia';
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
const pinia = createPinia().use(piniaPluginPersistedstate);
```
---
## Vue Router 4
```ts
// router/index.ts
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: () => import('./views/Home.vue') }, // lazy-loaded
{ path: '/user/:id', component: UserView, props: true }, // props:true passes params as props
{ path: '/:pathMatch(.*)*', component: NotFound }, // 404 catch-all
],
});
// Route guards
router.beforeEach(async (to, from) => {
if (to.meta.requiresAuth && !isLoggedIn()) return { name: 'Login' };
});
// In component:
import { useRouter, useRoute } from 'vue-router';
const router = useRouter();
const route = useRoute();
router.push({ name: 'User', params: { id: 42 } });
const userId = route.params.id as string;
```
---
## Templates
```vue
<template>
<!-- v-model -->
<input v-model="email" />
<MyInput v-model:title="title" v-model:count="count" />
<!-- named model -->
<!-- v-for with key (ALWAYS set key) -->
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
<!-- Dynamic components -->
<component :is="currentTab" />
<!-- Teleport β render in a different DOM node -->
<Teleport to="body"><Modal v-if="showModal" /></Teleport>
<!-- Transition -->
<Transition name="fade" mode="out-in">
<component :is="view" :key="view" />
</Transition>
<!-- Suspense (async components / composables with await) -->
<Suspense><AsyncComponent /><template #fallback>Loading...</template></Suspense>
</template>
<style>
/* Transition CSS */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
```
---
## Nuxt 4
```
auto-imports: ref, computed, useRoute, useFetch β no imports needed
composables/: auto-imported by filename
server/api/: server routes (GET/POST)
pages/: file-based routing
layouts/: layout components
middleware/: route guards
```
```ts
// pages/users/[id].vue
const { id } = useRoute().params; // auto-imported
const { data, error, refresh } = await useFetch(`/api/users/${id}`, {
lazy: false, // SSR: wait for data before rendering
server: true, // fetch on server (default)
transform: r => r.user,
});
// β TRAP: useFetch in Nuxt β @tanstack/react-query. It's Nuxt-specific.
// β TRAP: useAsyncData key must be UNIQUE per page/component
```
---
## Performance
- β
Use `v-memo` for expensive list items that rarely change
- β
`defineAsyncComponent(() => import("./Heavy.vue"))` for code splitting
- β
`:key` on `<component :is>` forces re-mount on route change (prevents stale state)
- β Avoid deeply nested reactive objects β use `shallowRef`/`shallowReactive` for large data
- β Never mutate props β emit events instead
## π¨ Edge-Case & Failure Mode Matrix
| Scenario | Risk | Production Mitigation |
|:---|:---|:---|
| **Empty or Null Inputs** | Unhandled exception or unexpected rendering collapse | Enforce fallback guards, optional chaining, and explicit empty state handlers |
| **Network Timeout / Latency** | Hanging operations or duplicate side-effects | Implement bounded abort controllers, exponential backoff, and idempotency keys |
| **Concurrency / Race Conditions** | Stale state overwrite or inconsistent data mutations | Use atomic transactions, mutex locking, or cancel-on-resubmit controls |
| **Invalid Schema / Malformed Payload** | Downstream runtime errors or security injection | Validate boundary payloads with Zod/Pydantic schemas prior to execution |
| **Resource / Memory Saturation** | OOM errors, frame drops, or memory leaks | Clean up listeners, cancel active timers, and enforce pagination/virtualization |
## ποΈ Tribunal Verification & Guardrails
**Active Reviewers:** `frontend-reviewer` Β· `type-safety` Β· `ui-ux-auditor` Β· `complexity-reviewer`
**Slash Command:** `/review` or `/tribunal-full`
### π¬ Evidence Standard (Tri-State Verification)
Every finding, audit statement, or completion claim must classify its factual certainty:
- **`[OBSERVED]`**: Directly confirmed in the codebase or verified via executed terminal command.
- **`[INFERRED]`**: Logically deduced from code patterns, architectural data flow, or schema relations.
- **`[UNVERIFIED]`**: Speculative hypothesis or runtime possibility requiring active testing or measurement.
### β
Pre-Flight Self-Audit Checklist
```
β
Are all component props strictly typed with zero implicit "any"?
β
Are responsive breakpoints, fluid typography, and optical balance verified?
β
Is accessibility (ARIA labels, keyboard navigation, contrast ratio >= 4.5:1) validated?
β
Are re-renders minimized and state lifecycles cleanly separated?
β
Did I verify all imported UI components and icon sets actually exist?
```
### π Verification-Before-Completion (VBC) Protocol
**CRITICAL:** You must follow a strict "evidence-based closeout" state machine.
- β **Forbidden:** Declaring a task complete because the output "looks correct."
- β
**Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing test suites, compiler success, or equivalent operational proof) that your output works as intended.
Attribution
Comments
Loading commentsβ¦