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-practicesskill if available. - If the project explicitly uses JSX, load
vue-jsx-best-practicesskill 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.mdreferences/sfc.mdreferences/component-data-flow.mdreferences/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 withcomputed. - 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-modelonly 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, andInjectionKeyas 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
- Built-in component
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.