Communitygithub.com

modèles-vue

Modèles de Composition API Vue.js 3, architecture de composants, bonnes pratiques de réactivité, gestion d'état Pinia, navigation Vue Router et modèles Nuxt SSR. S'active pour les projets Vue, Nuxt, Vite ou Pinia.

Qu'est-ce que modèles-vue ?

Ce skill fournit un guide complet pour le développement Vue.js 3 en utilisant la Composition API (`<script setup>`). Il couvre l'architecture des composants (conteneur vs présentation), la réactivité avec `ref`, `reactive`, et les fonctions avancées comme `useTemplateRef()` et `onWatcherCleanup()` introduites dans Vue 3.5+. Il détaille la gestion d'état avec Pinia (stores setup) et le routage avec Vue Router, y compris les gardes de navigation et les paramètres réactifs. Des sections spécifiques sont dédiées aux modèles Nuxt comme les auto-imports, `useAsyncData`/`useFetch`, les routes serveur et la config runtime. Il inclut également les bonnes pratiques de test avec Vitest et Vue Test Utils, une table des anti-patrons (par exemple, la déstructuration de props avant Vue 3.5 ou les mixins), et des techniques de performance (comme `v-memo`, `shallowRef` et le chargement paresseux). Le skill aide les développeurs à écrire du code Vue/maintenable et performant, que ce soit dans une application Vanilla Vue ou un projet Nuxt.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/vue-patterns

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Modèles et Bonnes Pratiques Vue.js

Guide complet pour le développement Vue.js 3 avec la Composition API (<script setup>), couvrant la conception de composants, la réactivité, la gestion d'état, le routage, les tests et les modèles SSR. Des conseils spécifiques à Nuxt sont inclus lorsqu'ils diffèrent de Vue standard.

Quand activer

Activez ce skill quand :

  • Le projet utilise Vue.js (toute version), Nuxt, Vite + Vue, ou Pinia.
  • L'utilisateur pose des questions sur l'architecture des composants Vue, les composables, la réactivité ou la gestion d'état.
  • Vous examinez des composants monofichiers Vue (fichiers .vue).
  • Vous configurez Vue Router, les stores Pinia, ou la configuration Vite/Vitest.
  • Vous discutez de performances, de sécurité ou de modèles SSR spécifiques à Vue.

1. Structure du Projet

Disposition recommandée (par fonctionnalité)

src/
├── api/              # Client API et définitions de points de terminaison
├── assets/           # Ressources statiques (images, polices, icônes)
├── components/       # Composants partagés/réutilisables
│   ├── base/         # Primitives d'interface de base (Bouton, Champ, Modale)
│   └── features/     # Composants partagés spécifiques à une fonctionnalité
├── composables/      # Logique réutilisable de la Composition API
├── layouts/          # Mises en page (optionnel)
├── pages/            # Composants de page au niveau des routes
├── router/           # Configuration Vue Router
├── stores/           # Stores Pinia
├── types/            # Définitions de types TypeScript
├── utils/            # Fonctions utilitaires pures
└── App.vue           # Composant racine

Nommage des fichiers

ConventionQuand l'utiliser
PascalCase.vueTous les composants (imposé par vue/multi-word-component-names)
useCamelCase.tsComposables
camelCase.tsUtilitaires, clients API, types
Répertoires kebab-caseSegments de route, dossiers de fonctionnalités

2. Architecture des Composants

Ordre des composants monofichiers

<script setup lang="ts">
// 1. Imports (vue → écosystème → absolu → relatif)
// 2. Props & Événements & Slots
// 3. Composables
// 4. État local (ref/reactive)
// 5. Propriétés calculées
// 6. Méthodes
// 7. Observateurs
// 8. Hooks de cycle de vie
</script>

<template>
  <!-- Contenu du template -->
</template>

<style scoped>
  /* Styles encapsulés */
</style>

Composants de présentation vs conteneur

  • Composants conteneur : Gèrent la récupération des données, l'état et les effets de bord. Affichent les composants de présentation.
  • Composants de présentation : Reçoivent des props, émettent des événements. Pas d'appels API, pas d'accès au store. Rendu pur.

Bonnes pratiques pour les props

// Props typées avec valeurs par défaut
interface Props {
  label: string;
  variant?: "primary" | "secondary";
  disabled?: boolean;
  items: Item[];
}

const props = withDefaults(defineProps<Props>(), {
  variant: "primary",
  disabled: false,
});
  • Fournissez toujours type, et required/default le cas échéant.
  • Props booléennes : isXxx, hasXxx, canXxx.
  • Ne mutez jamais les props — émettez des événements à la place.
  • Pour la liaison v-model, utilisez defineModel() (Vue 3.4+) ou modelValue + update:modelValue.

Événements

const emit = defineEmits<{
  submit: [];
  "update:modelValue": [value: string];
  select: [id: string, index: number];
}>();
  • Utilisez le kebab-case dans les templates (@update:model-value).
  • Utilisez le camelCase dans le script (emit("update:modelValue", val)).

3. Composables (Logique réutilisable)

Structure

// composables/useDebounce.ts
export function useDebounce<T>(value: MaybeRef<T>, delay: number): Ref<T> {
  const debounced = ref(toValue(value)) as Ref<T>;

  let timer: ReturnType<typeof setTimeout>;
  watch(
    () => toValue(value),
    (newVal) => {
      clearTimeout(timer);
      timer = setTimeout(() => { debounced.value = newVal; }, delay);
    }
  );

  onUnmounted(() => clearTimeout(timer));
  return readonly(debounced);
}

Règles

  • Doit commencer par le préfixe use.
  • Retournez des valeurs réactives (ref, computed, reactive), jamais de primitives simples.
  • Acceptez des entrées réactives via MaybeRef / toRef() / toValue().
  • Nettoyez les effets de bord dans onUnmounted ou onCleanup d'observateur.
  • Pas d'effets de bord au niveau du module.

vs Mixins

Les composables remplacent entièrement les mixins Vue 2 :

  • Mixins : Flux de données opaque, collisions de source de vérité, conflits de noms.
  • Composables : Importations explicites, valeurs de retour claires, composables et arborescences optimisables.

4. Gestion d'État

Quand utiliser quoi

ModèleCas d'utilisation
ref() / reactive()État local du composant
Props + ÉvénementsCommunication parent-enfant
Provide / InjectThème, configuration, API de plugin
Store PiniaÉtat global, partagé, complexe
Composable d'état serveurDonnées API avec cache (envelopper fetch/TanStack Query)

Store Pinia Setup (Recommandé)

// stores/useCartStore.ts
export const useCartStore = defineStore("cart", () => {
  const items = ref<CartItem[]>([]);
  const isLoading = ref(false);

  const totalPrice = computed(() =>
    items.value.reduce((sum, i) => sum + i.price * i.quantity, 0)
  );
  const itemCount = computed(() =>
    items.value.reduce((sum, i) => sum + i.quantity, 0)
  );

  async function addItem(productId: string) {
    isLoading.value = true;
    try {
      const item = await fetchProduct(productId);
      const existing = items.value.find(i => i.id === item.id);
      if (existing) existing.quantity++;
      else items.value.push({ ...item, quantity: 1 });
    } finally {
      isLoading.value = false;
    }
  }

  return { items, isLoading, totalPrice, itemCount, addItem };
});
  • Utilisez la syntaxe Setup Store (pas Options Store).
  • Privilégiez les actions pour les mutations métier et $patch() pour les mises à jour groupées.
  • Chaque action asynchrone : gérez le chargement + succès + erreur.

5. Vue Router

Définitions de routes

const routes = [
  {
    path: "/users/:id",
    name: "user-detail",
    component: () => import("@/pages/UserDetail.vue"), // paresseux
    props: true, // passer les paramètres comme props
    meta: { requiresAuth: true },
  },
];

Gardes de navigation

router.beforeEach((to, from) => {
  const { isLoggedIn } = useAuthStore();
  if (to.meta.requiresAuth && !isLoggedIn) {
    return { name: "login", query: { redirect: to.fullPath } };
  }
});

Paramètres de route réactifs

Lorsqu'un composant reste monté mais que les paramètres de route changent :

const route = useRoute();
const id = computed(() => route.params.id as string);
watch(id, (newId) => fetchItem(newId));

6. Modèles de Template

Syntaxe du template

<!-- v-if/v-else-if/v-else -->
<div v-if="isLoading">Chargement...</div>
<div v-else-if="error">Erreur : {{ error }}</div>
<div v-else>{{ content }}</div>

<!-- v-show pour les basculements fréquents -->
<div v-show="isOpen">Contenu basculé</div>

<!-- v-for avec clés stables -->
<div v-for="item in items" :key="item.id">{{ item.name }}</div>

<!-- Liste filtrée par calcul (pas v-if + v-for sur le même élément) -->
<div v-for="item in activeItems" :key="item.id">{{ item.name }}</div>

<!-- Gestion d'événements -->
<form @submit.prevent="handleSubmit">
  <button type="submit">Enregistrer</button>
</form>

<!-- v-model -->
<input v-model="name" />
<CustomInput v-model="value" v-model:title="title" />

7. Performances

TechniqueQuand l'utiliser
v-memoÉléments de liste qui changent rarement
v-onceContenu rendu une fois et statique pour toujours
shallowRef()Grandes structures de données remplacées en bloc
shallowReactive()Seules les propriétés de premier niveau sont réactives
v-show plutôt que v-ifBasculements de visibilité fréquents
<KeepAlive :max="10">Mettre en cache les vues basculées
Routes paresseuses() => import(...) pour les routes non critiques
SuspenseChargement de composant asynchrone avec fallback

8. Tests

Stack

  • Vitest pour les tests unitaires et de composants
  • Vue Test Utils pour le montage et l'interaction
  • @pinia/testing pour le mock des stores
  • Playwright pour les tests E2E

Modèle de test de composant

import { mount } from "@vue/test-utils";
import { createPinia, setActivePinia } from "pinia";
import UserCard from "./UserCard.vue";

beforeEach(() => { setActivePinia(createPinia()); });

it("rend et émet", async () => {
  const wrapper = mount(UserCard, {
    props: { user: { id: "1", name: "Alice" } },
  });
  expect(wrapper.text()).toContain("Alice");
  await wrapper.find("button").trigger("click");
  expect(wrapper.emitted("select")![0]).toEqual(["1"]);
});

9. Modèles Spécifiques à Nuxt

Auto-importations

Nuxt auto-importe ref, computed, watch, useFetch, useAsyncData, etc. Utilisez-les directement sans importation. Pour les projets non Nuxt, importez toujours explicitement.

useAsyncData / useFetch

const { data: user, pending, error, refresh } = await useAsyncData(
  "user", // clé unique pour le cache
  () => $fetch(`/api/users/${id}`),
);

const { data: posts } = await useFetch("/api/posts", {
  query: { page: 1 },
  key: "posts-page-1", // déduplication des requêtes
});

Routes serveur

// server/api/users/[id].ts
export default defineEventHandler(async (event) => {
  const { id } = await getValidatedRouterParams(event, z.object({
    id: z.string().uuid(),
  }).parse);
  // ... récupérer et retourner
});

Configuration runtime

// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    // serveur uniquement
    apiSecret: "",
    // public (exposé au client)
    public: {
      apiBase: "https://api.example.com",
    },
  },
});

10. Nouvelles API Vue 3.5+

Déstructuration réactive des props

Vue 3.5 a stabilisé la déstructuration réactive des props — les variables déstructurées de defineProps() sont automatiquement réactives :

// Vue 3.5+ : les props déstructurées sont réactives (pas besoin de toRefs)
const { count = 0, msg = "hello" } = defineProps<{
  count?: number;
  msg?: string;
}>();

// Limitation : impossible d'observer directement une prop déstructurée
watch(() => count, (newVal) => { ... }); // PASS : un getter est requis

useTemplateRef()

Remplacez les refs simples nommées par useTemplateRef() pour les références de template :

import { useTemplateRef } from "vue";
const inputEl = useTemplateRef<HTMLInputElement>("input");
// "input" correspond à l'attribut ref="input" dans le template, pas au nom de la variable

Prend en charge les IDs ref dynamiques : useTemplateRef(dynamicRefId).

onWatcherCleanup()

API de nettoyage d'observateur importable globalement (Vue 3.5+). Elle doit être appelée de manière synchrone à l'intérieur du callback de l'observateur :

import { watch, onWatcherCleanup } from "vue";

watch(userId, async (newId) => {
  const controller = new AbortController();
  onWatcherCleanup(() => controller.abort());
  // ... récupérer avec signal
});

useId()

Génération d'ID unique stable pour le SSR pour les éléments de formulaire et l'accessibilité :

import { useId } from "vue";
const id = useId();

Téléportation defer

<Teleport defer> permet de téléporter vers des cibles rendues dans le même cycle :

<Teleport defer to="#container">Contenu</Teleport>
<div id="container"></div>

Hydratation paresseuse (SSR)

defineAsyncComponent() prend désormais en charge la stratégie hydrate :

import { defineAsyncComponent, hydrateOnVisible } from "vue";
const AsyncComp = defineAsyncComponent({
  loader: () => import("./Comp.vue"),
  hydrate: hydrateOnVisible(),
});

Anti-patrons

Anti-patronPourquoi c'est fauxLa correction
Déstructuration de defineProps() (Vue < 3.5)Capture un instantané, perd la réactivitéAccéder via props.xxx ou utiliser toRefs()
watch() sur une prop déstructurée (Vue 3.5+)Erreur à la compilation — les props déstructurées ne peuvent pas être observées directementUtiliser un getter enveloppant : watch(() => count, ...)
v-if + v-for sur le même élémentOrdre d'exécution ambiguUtiliser un tableau filtré calculé
Clé v-for = indexÉtat cassé lors du réordonnancementUtiliser des IDs de base de données stables
Muter les propsViole le flux de données unidirectionnelÉmettre des événements ou utiliser v-model
v-html avec contenu utilisateurVulnérabilité XSSNettoyer avec DOMPurify
Mixins dans Vue 3Opaque, sujet aux collisionsRemplacer par des composables
Effets de bord au niveau du module dans un composablePartagés entre instancesLimiter la portée dans onMounted + onUnmounted
reactive() pour un état remplaçableLe remplacement casse la réactivitéUtiliser ref() à la place
Observateur sans nettoyageFuites mémoire, conditions de courseUtiliser onCleanup ou onWatcherCleanup() (Vue 3.5+)
Options API dans du nouveau code Vue 3L'écosystème évolue vers la Composition APIUtiliser <script setup>
Ref simple pour les références de templatePas de support de ref dynamique, correspondance de nom fragileUtiliser useTemplateRef() (Vue 3.5+)

Skills associés

  • accessibility — ARIA, HTML sémantique, gestion du focus
  • frontend-patterns — Architecture frontend multi-cadres
  • typescript — Bonnes pratiques TypeScript appliquées aux projets Vue
  • coding-standards — Standards généraux de qualité de code

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Skills associés