Vue Best Practices Workflow
Use this skill as an instruction set. Follow the workflow in order unless the user explicitly asks for a different order.
Core Principles
- Keep state predictable: one source of truth, derive everything else.
- Make data flow explicit: Props down, Events up for most cases.
- Favor small, focused components: easier to test, reuse, and maintain.
- Avoid unnecessary re-renders: use computed properties and watchers wisely.
- Readability counts: write clear, self-documenting code.
1) Confirm architecture before coding (required)
- Default stack: Vue 3 + Composition API +
<script setup lang="ts">.
- If the project explicitly uses Options API, load
vue-options-api-best-practices skill if available.
- If the project explicitly uses JSX, load
vue-jsx-best-practices skill if available.
1.1 Must-read core references (required)
- Before implementing any Vue task, make sure to read and apply these core references:
references/reactivity.md
references/sfc.md
references/component-data-flow.md
references/composables.md
- Keep these references in active working context for the entire task, not only when a specific issue appears.
1.2 Plan component boundaries before coding (required)
Create a brief component map before implementation for any non-trivial feature.
- Define each component's single responsibility in one sentence.
- Keep entry/root and route-level view components as composition surfaces by default.
- Move feature UI and feature logic out of entry/root/view components unless the task is intentionally a tiny single-file demo.
- Define props/emits contracts for each child component in the map.
- Prefer a feature folder layout (
components/<feature>/..., composables/use<Feature>.ts) when adding more than one component.
2) Apply essential Vue foundations (required)
These are essential, must-know foundations. Apply all of them in every Vue task using the core references already loaded in section 1.1.
Reactivity
- Must-read reference from
1.1: reactivity
- Keep source state minimal (
ref/reactive), derive everything possible with computed.
- Use watchers for side effects if needed.
- Avoid recomputing expensive logic in templates.
SFC structure and template safety
- Must-read reference from
1.1: sfc
- Keep SFC sections in this order:
<script> → <template> → <style>.
- Keep SFC responsibilities focused; split large components.
- Keep templates declarative; move branching/derivation to script.
- Apply Vue template safety rules (
v-html, list rendering, conditional rendering choices).
Keep components focused
Split a component when it has more than one clear responsibility (e.g. data orchestration + UI, or multiple independent UI sections).
- Prefer smaller components + composables over one “mega component”
- Move UI sections into child components (props in, events out).
- Move state/side effects into composables (
useXxx()).
Apply objective split triggers. Split the component if any condition is true:
- It owns both orchestration/state and substantial presentational markup for multiple sections.
- It has 3+ distinct UI sections (for example: form, filters, list, footer/status).
- A template block is repeated or could become reusable (item rows, cards, list entries).
Entry/root and route view rule:
- Keep entry/root and route view components thin: app shell/layout, provider wiring, and feature composition.
- Do not place full feature implementations in entry/root/view components when those features contain independent parts.
- For CRUD/list features (todo, table, catalog, inbox), split at least into:
- feature container component
- input/form component
- list (and/or item) component
- footer/actions or filter/status component
- Allow a single-file implementation only for very small throwaway demos; if chosen, explicitly justify why splitting is unnecessary.
Component data flow
- Must-read reference from
1.1: component-data-flow
- Use props down, events up as the primary model.
- Use
v-model only for true two-way component contracts.
- Use provide/inject only for deep-tree dependencies or shared context.
- Keep contracts explicit and typed with
defineProps, defineEmits, and InjectionKey as needed.
Composables
- Must-read reference from
1.1: composables
- Extract logic into composables when it is reused, stateful, or side-effect heavy.
- Keep composable APIs small, typed, and predictable.
- Separate feature logic from presentational components.
Vue 3.5+ APIs (apply on Vue 3.5 or newer)
- Prefer destructure defaults over
withDefaults(); mind the getter-boundary rule -> reactive-props-destructure
- Use 3.5 built-ins before hand-rolling:
useId, onWatcherCleanup, <Teleport defer>, lazy hydration -> vue-3-5-helpers
3) Consider optional features only when requirements call for them
3.1 Standard optional features
Do not add these by default. Load the matching reference only when the requirement exists.
- Slots: parent needs to control child content/layout -> component-slots
- Fallthrough attributes: wrapper/base components must forward attrs/events safely -> component-fallthrough-attrs
- Built-in component
<KeepAlive> for stateful view caching -> component-keep-alive
- Built-in component
<Teleport> for overlays/portals -> component-teleport
- Built-in component
<Suspense> for async subtree fallback boundaries -> component-suspense
- Animation-related features: pick the simplest approach that matches the required motion behavior.
- Built-in component
<Transition> for enter/leave effects -> transition
- Built-in component
<TransitionGroup> for animated list mutations -> transition-group
- Class-based animation for non-enter/leave effects -> animation-class-based-technique
- State-driven animation for user-input-driven animation -> animation-state-driven-technique
3.2 Less-common optional features
Use these only when there is explicit product or technical need.
- Directives: behavior is DOM-specific and not a good composable/component fit -> directives
- Async components: heavy/rarely-used UI should be lazy loaded -> component-async
- Render functions only when templates cannot express the requirement -> render-functions
- Plugins when behavior must be installed app-wide -> plugins
- State management patterns: app-wide shared state crosses feature boundaries -> state-management
4) Run performance optimization after behavior is correct
Performance work is a post-functionality pass. Do not optimize before core behavior is implemented and verified.
- Large list rendering bottlenecks -> perf-virtualize-large-lists
- Static subtrees re-rendering unnecessarily -> perf-v-once-v-memo-directives
- Over-abstraction in hot list paths -> perf-avoid-component-abstraction-in-lists
- Expensive updates triggered too often -> updated-hook-performance
Experimental: a measured rendering hotspot may justify Vapor Mode (Vue 3.6, opt-in, unstable) -> vapor-mode. Do not enable by default.
5) Final self-check before finishing
- Core behavior works and matches requirements.
- All must-read references were read and applied.
- Reactivity model is minimal and predictable.
- SFC structure and template rules are followed.
- Components are focused and well-factored, splitting when needed.
- Entry/root and route view components remain composition surfaces unless there is an explicit small-demo exception.
- Component split decisions are explicit and defensible (responsibility boundaries are clear).
- Data flow contracts are explicit and typed.
- Composables are used where reuse/complexity justifies them.
- Moved state/side effects into composables if applicable
- Optional features are used only when requirements demand them.
- Performance changes were applied only after functionality was complete.
1---2name: vue-best-practices3description: MUST be used for Vue.js tasks. Strongly recommends Composition API with `<script setup>` and TypeScript as the standard approach. Covers Vue 3, SSR, Volar, vue-tsc. Load for any Vue, .vue files, Vue Router, Pinia, or Vite with Vue work. ALWAYS use Composition API unless the project explicitly requires Options API.4license: MIT5---67# Vue Best Practices Workflow89Use this skill as an instruction set. Follow the workflow in order unless the user explicitly asks for a different order.1011## Core Principles12- **Keep state predictable:** one source of truth, derive everything else.13- **Make data flow explicit:** Props down, Events up for most cases.14- **Favor small, focused components:** easier to test, reuse, and maintain.15- **Avoid unnecessary re-renders:** use computed properties and watchers wisely.16- **Readability counts:** write clear, self-documenting code.1718## 1) Confirm architecture before coding (required)1920- Default stack: Vue 3 + Composition API + `<script setup lang="ts">`.21- If the project explicitly uses Options API, load `vue-options-api-best-practices` skill if available.22- If the project explicitly uses JSX, load `vue-jsx-best-practices` skill if available.2324### 1.1 Must-read core references (required)2526- Before implementing any Vue task, make sure to read and apply these core references:27 - `references/reactivity.md`28 - `references/sfc.md`29 - `references/component-data-flow.md`30 - `references/composables.md`31- Keep these references in active working context for the entire task, not only when a specific issue appears.3233### 1.2 Plan component boundaries before coding (required)3435Create a brief component map before implementation for any non-trivial feature.3637- Define each component's single responsibility in one sentence.38- Keep entry/root and route-level view components as composition surfaces by default.39- Move feature UI and feature logic out of entry/root/view components unless the task is intentionally a tiny single-file demo.40- Define props/emits contracts for each child component in the map.41- Prefer a feature folder layout (`components/<feature>/...`, `composables/use<Feature>.ts`) when adding more than one component.4243## 2) Apply essential Vue foundations (required)4445These are essential, must-know foundations. Apply all of them in every Vue task using the core references already loaded in section `1.1`.4647### Reactivity4849- Must-read reference from `1.1`: [reactivity](references/reactivity.md)50- Keep source state minimal (`ref`/`reactive`), derive everything possible with `computed`.51- Use watchers for side effects if needed.52- Avoid recomputing expensive logic in templates.5354### SFC structure and template safety5556- Must-read reference from `1.1`: [sfc](references/sfc.md)57- Keep SFC sections in this order: `<script>` → `<template>` → `<style>`.58- Keep SFC responsibilities focused; split large components.59- Keep templates declarative; move branching/derivation to script.60- Apply Vue template safety rules (`v-html`, list rendering, conditional rendering choices).6162### Keep components focused6364Split a component when it has **more than one clear responsibility** (e.g. data orchestration + UI, or multiple independent UI sections).6566- Prefer **smaller components + composables** over one “mega component”67- Move **UI sections** into child components (props in, events out).68- Move **state/side effects** into composables (`useXxx()`).6970Apply objective split triggers. Split the component if **any** condition is true:7172- It owns both orchestration/state and substantial presentational markup for multiple sections.73- It has 3+ distinct UI sections (for example: form, filters, list, footer/status).74- A template block is repeated or could become reusable (item rows, cards, list entries).7576Entry/root and route view rule:7778- Keep entry/root and route view components thin: app shell/layout, provider wiring, and feature composition.79- Do not place full feature implementations in entry/root/view components when those features contain independent parts.80- For CRUD/list features (todo, table, catalog, inbox), split at least into:81 - feature container component82 - input/form component83 - list (and/or item) component84 - footer/actions or filter/status component85- Allow a single-file implementation only for very small throwaway demos; if chosen, explicitly justify why splitting is unnecessary.8687### Component data flow8889- Must-read reference from `1.1`: [component-data-flow](references/component-data-flow.md)90- Use props down, events up as the primary model.91- Use `v-model` only for true two-way component contracts.92- Use provide/inject only for deep-tree dependencies or shared context.93- Keep contracts explicit and typed with `defineProps`, `defineEmits`, and `InjectionKey` as needed.9495### Composables9697- Must-read reference from `1.1`: [composables](references/composables.md)98- Extract logic into composables when it is reused, stateful, or side-effect heavy.99- Keep composable APIs small, typed, and predictable.100- Separate feature logic from presentational components.101102### Vue 3.5+ APIs (apply on Vue 3.5 or newer)103104- Prefer destructure defaults over `withDefaults()`; mind the getter-boundary rule -> [reactive-props-destructure](references/reactive-props-destructure.md)105- Use 3.5 built-ins before hand-rolling: `useId`, `onWatcherCleanup`, `<Teleport defer>`, lazy hydration -> [vue-3-5-helpers](references/vue-3-5-helpers.md)106107## 3) Consider optional features only when requirements call for them108109### 3.1 Standard optional features110111Do not add these by default. Load the matching reference only when the requirement exists.112113- Slots: parent needs to control child content/layout -> [component-slots](references/component-slots.md)114- Fallthrough attributes: wrapper/base components must forward attrs/events safely -> [component-fallthrough-attrs](references/component-fallthrough-attrs.md)115- Built-in component `<KeepAlive>` for stateful view caching -> [component-keep-alive](references/component-keep-alive.md)116- Built-in component `<Teleport>` for overlays/portals -> [component-teleport](references/component-teleport.md)117- Built-in component `<Suspense>` for async subtree fallback boundaries -> [component-suspense](references/component-suspense.md)118- Animation-related features: pick the simplest approach that matches the required motion behavior.119 - Built-in component `<Transition>` for enter/leave effects -> [transition](references/component-transition.md)120 - Built-in component `<TransitionGroup>` for animated list mutations -> [transition-group](references/component-transition-group.md)121 - Class-based animation for non-enter/leave effects -> [animation-class-based-technique](references/animation-class-based-technique.md)122 - State-driven animation for user-input-driven animation -> [animation-state-driven-technique](references/animation-state-driven-technique.md)123124### 3.2 Less-common optional features125126Use these only when there is explicit product or technical need.127128- Directives: behavior is DOM-specific and not a good composable/component fit -> [directives](references/directives.md)129- Async components: heavy/rarely-used UI should be lazy loaded -> [component-async](references/component-async.md)130- Render functions only when templates cannot express the requirement -> [render-functions](references/render-functions.md)131- Plugins when behavior must be installed app-wide -> [plugins](references/plugins.md)132- State management patterns: app-wide shared state crosses feature boundaries -> [state-management](references/state-management.md)133134## 4) Run performance optimization after behavior is correct135136Performance work is a post-functionality pass. Do not optimize before core behavior is implemented and verified.137138- Large list rendering bottlenecks -> [perf-virtualize-large-lists](references/perf-virtualize-large-lists.md)139- Static subtrees re-rendering unnecessarily -> [perf-v-once-v-memo-directives](references/perf-v-once-v-memo-directives.md)140- Over-abstraction in hot list paths -> [perf-avoid-component-abstraction-in-lists](references/perf-avoid-component-abstraction-in-lists.md)141- Expensive updates triggered too often -> [updated-hook-performance](references/updated-hook-performance.md)142143Experimental: a measured rendering hotspot may justify Vapor Mode (Vue 3.6, opt-in, unstable) -> [vapor-mode](references/vapor-mode.md). Do not enable by default.144145## 5) Final self-check before finishing146147- Core behavior works and matches requirements.148- All must-read references were read and applied.149- Reactivity model is minimal and predictable.150- SFC structure and template rules are followed.151- Components are focused and well-factored, splitting when needed.152- Entry/root and route view components remain composition surfaces unless there is an explicit small-demo exception.153- Component split decisions are explicit and defensible (responsibility boundaries are clear).154- Data flow contracts are explicit and typed.155- Composables are used where reuse/complexity justifies them.156- Moved state/side effects into composables if applicable157- Optional features are used only when requirements demand them.158- Performance changes were applied only after functionality was complete.