Skip to content

Commit b3c89e9

Browse files
feat(instructions): add comprehensive Vue 3 development instructions (#1941)
Add instructions/vue.instructions.md covering the Vue 3 feature surface: Composition API and <script setup>, the full reactivity system, compiler macros (defineModel/defineSlots/defineOptions), built-in components (Teleport/Suspense/Transition/KeepAlive), provide/inject, composables, Pinia, Vue Router, TypeScript, styling, forms, error handling, performance, SSR, accessibility, security, and testing. Regenerate docs/README.instructions.md index entry. Co-authored-by: Lloouujjiinn <281355774+fhwvtqdc2q-svg@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 755571d commit b3c89e9

2 files changed

Lines changed: 175 additions & 0 deletions

File tree

docs/README.instructions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,5 +204,6 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-instructions) for guidelines on
204204
| [Use Cliche Data in Documentation](../instructions/use-cliche-data-in-docs.instructions.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fuse-cliche-data-in-docs.instructions.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fuse-cliche-data-in-docs.instructions.md) | Ensure documentation and examples use only generic, cliche placeholder data — never real or sensitive data sourced from local scripts, configuration, task files, or prompt context. |
205205
| [Use Code Components in Power Pages](../instructions/pcf-power-pages.instructions.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fpcf-power-pages.instructions.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fpcf-power-pages.instructions.md) | Using code components in Power Pages sites |
206206
| [Visual Studio Extension Development with Community.VisualStudio.Toolkit](../instructions/vsixtoolkit.instructions.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fvsixtoolkit.instructions.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fvsixtoolkit.instructions.md) | Guidelines for Visual Studio extension (VSIX) development using Community.VisualStudio.Toolkit |
207+
| [Vue 3 Development Instructions](../instructions/vue.instructions.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fvue.instructions.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fvue.instructions.md) | Comprehensive Vue 3 development standards and best practices: Composition API, `<script setup>`, the full reactivity system, compiler macros (defineModel/defineSlots/defineOptions), built-in components (Teleport/Suspense/Transition/KeepAlive), provide/inject, composables, Pinia, Vue Router, TypeScript, testing, performance, SSR, and security. |
207208
| [WinUI 3 / Windows App SDK](../instructions/winui3.instructions.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fwinui3.instructions.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fwinui3.instructions.md) | WinUI 3 and Windows App SDK coding guidelines. Prevents common UWP API misuse, enforces correct XAML namespaces, threading, windowing, and MVVM patterns for desktop Windows apps. |
208209
| [WordPress Development — Copilot Instructions](../instructions/wordpress.instructions.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fwordpress.instructions.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fwordpress.instructions.md) | Coding, security, and testing rules for WordPress plugins and themes |

instructions/vue.instructions.md

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
---
2+
description: 'Comprehensive Vue 3 development standards and best practices: Composition API, `<script setup>`, the full reactivity system, compiler macros (defineModel/defineSlots/defineOptions), built-in components (Teleport/Suspense/Transition/KeepAlive), provide/inject, composables, Pinia, Vue Router, TypeScript, testing, performance, SSR, and security.'
3+
applyTo: '**/*.vue, **/*.ts, **/*.js, **/*.css, **/*.scss'
4+
---
5+
6+
# Vue 3 Development Instructions
7+
8+
Authoritative guidance for building production-grade Vue 3 applications. Default to the **Composition API** with `<script setup lang="ts">`, the modern reactivity system, and the official ecosystem (Pinia, Vue Router, Vite, Vitest). Prefer the idioms below over legacy Options API and Vue 2 patterns.
9+
10+
## Project Context
11+
- Vue 3.4+ (use 3.5+ features such as `useTemplateRef`, `useId`, and reactive props destructuring where the project's version allows).
12+
- `<script setup lang="ts">` single-file components (SFCs) as the default authoring style.
13+
- TypeScript everywhere: components, composables, stores, and router.
14+
- Pinia for state management; Vue Router for routing; Vite for build/dev.
15+
- Vitest + Vue Test Utils (or Testing Library for Vue) for tests.
16+
17+
## Authoring Style & Component Design
18+
- Use `<script setup>` — it is more concise, faster, and has better type inference than `setup()` or the Options API.
19+
- One responsibility per component; split large components into smaller focused ones plus composables.
20+
- Order an SFC as `<script setup>`, then `<template>`, then `<style scoped>`.
21+
- Name components in PascalCase; use multi-word names (e.g. `UserCard`, not `Card`) to avoid clashing with native elements.
22+
- Co-locate component-specific types, and lift shared types into a `types/` module.
23+
24+
## Compiler Macros (no imports needed)
25+
- `defineProps<T>()` — declare typed props from a TypeScript interface/type for full inference.
26+
- `withDefaults(defineProps<T>(), { ... })` — provide prop defaults (or use reactive props destructuring with defaults in 3.5+).
27+
- `defineEmits<{ change: [id: number]; update: [value: string] }>()` — declare typed events.
28+
- `defineModel<T>()` (3.4+) — the canonical way to implement `v-model` on a component; supports multiple models, arguments, and modifiers.
29+
- `defineExpose({ ... })` — explicitly expose a public imperative API; expose nothing by default.
30+
- `defineSlots<{ default(props: { item: T }): any }>()` — type named/scoped slots.
31+
- `defineOptions({ name, inheritAttrs })` — set component options inside `<script setup>`.
32+
- Never mutate props directly — emit an event, use `defineModel`, or derive local state with `computed`/`ref`.
33+
34+
## Reactivity System
35+
### Core primitives
36+
- `ref()` for primitives and single replaceable references; access via `.value` in script (auto-unwrapped in templates).
37+
- `reactive()` for deep-reactive objects/collections; never destructure it directly (breaks reactivity) — use `toRefs()`/`toRef()`.
38+
- `computed()` for derived values; keep getters pure and side-effect free. Use writable computed (`get`/`set`) for two-way derived state.
39+
- Prefer `computed` over `watch` whenever you are *deriving* a value rather than performing a side effect.
40+
41+
### Watchers
42+
- `watch(source, cb, options)` for explicit dependencies; `watchEffect(cb)` for auto-tracked dependencies.
43+
- Use watch options deliberately: `{ immediate: true }`, `{ deep: true }`, `{ once: true }` (3.4+), and `flush: 'post'` when you need the DOM updated first.
44+
- Register cleanup with the `onCleanup`/`onWatcherCleanup` callback to cancel stale async work (debounce, fetch, listeners).
45+
- Stop manual watchers via their returned handle when they outlive their natural scope.
46+
47+
### Advanced reactivity (use intentionally)
48+
- `shallowRef` / `shallowReactive` for large or externally-managed data to skip deep tracking.
49+
- `readonly()` to hand out immutable views of shared state.
50+
- `toRef` / `toRefs` to keep reactivity when destructuring; `toRaw`/`markRaw` to opt out for non-reactive objects (e.g. class instances, 3rd-party clients).
51+
- `effectScope()` to group and dispose related effects together (useful in composables/libraries).
52+
- `customRef` for debounced/throttled or storage-backed refs.
53+
54+
## Composables (reusable logic)
55+
- Extract stateful, reusable logic into `useXxx()` functions under `composables/`.
56+
- Accept refs/getters as inputs and return refs/computed; use `toValue()`/`MaybeRefOrGetter` to normalize ref-or-plain inputs.
57+
- Set up and tear down inside the composable (`onMounted`/`onUnmounted` or `tryOnScopeDispose`) so callers don't leak.
58+
- Keep composables synchronous in their setup phase; expose async actions as returned functions.
59+
- Reach for VueUse for common needs instead of re-implementing (e.g. `useStorage`, `useEventListener`, `useDebounceFn`).
60+
61+
## Lifecycle & Effects
62+
- Use `onMounted`, `onBeforeMount`, `onUpdated`, `onBeforeUnmount`, `onUnmounted`, `onActivated`/`onDeactivated` (with `<KeepAlive>`), and `onErrorCaptured`.
63+
- Always clean up timers, listeners, observers, and subscriptions in `onUnmounted`.
64+
- Guard browser-only APIs (`window`, `document`) for SSR; run them in `onMounted`.
65+
66+
## Template Best Practices
67+
- Always set a stable, unique `:key` on `v-for`; never use the array index when items can reorder or mutate.
68+
- Never put `v-if` and `v-for` on the same element — filter via a `computed` instead.
69+
- `v-show` for frequently toggled elements; `v-if` for conditional mounting.
70+
- Use `v-memo` to skip re-rendering of expensive static subtrees, and `v-once` for content that renders a single time.
71+
- Use the `:` (v-bind) and `@` (v-on) shorthands consistently; group nodes with `<template>` to avoid wrapper elements.
72+
- Avoid heavy expressions in templates — move them to `computed` or methods.
73+
74+
## Slots
75+
- Use named slots for layout extension and scoped slots (`<slot :item="item" />` + `#default="{ item }"`) to expose data to the parent.
76+
- Provide sensible fallback slot content.
77+
- Use the `v-slot` (`#`) shorthand and dynamic slot names where appropriate.
78+
79+
## Built-in Components
80+
- `<Teleport to="body">` for modals, toasts, and tooltips that must escape overflow/stacking contexts.
81+
- `<Suspense>` with `#default`/`#fallback` for async setup and lazy components; pair with error handling.
82+
- `<Transition>` / `<TransitionGroup>` for enter/leave and list animations (set `:key` on grouped items).
83+
- `<KeepAlive>` (with `include`/`exclude`/`max`) to cache component state across toggles; handle `onActivated`/`onDeactivated`.
84+
- `<component :is="...">` for dynamic components; `defineAsyncComponent(() => import('...'))` for code-split/lazy loading with loading/error components.
85+
86+
## Provide / Inject (dependency injection)
87+
- Type injections with an `InjectionKey<T>` (`Symbol`) for safety: `provide(key, value)` / `inject(key)`.
88+
- Provide a default or assert presence to avoid `undefined`.
89+
- Prefer `readonly()` when providing state that children should not mutate; expose explicit updater functions instead.
90+
- Use injection for cross-cutting concerns; use Pinia for app-wide shared state.
91+
92+
## Custom Directives & Plugins
93+
- Author directives as objects with `mounted`/`updated` (etc.) hooks; keep them DOM-focused (e.g. `v-focus`, `v-click-outside`).
94+
- Encapsulate global setup (router, pinia, i18n, UI libs) as plugins via `app.use(...)`; register global config in `main.ts`.
95+
96+
## State Management with Pinia
97+
- Use Pinia for shared/cross-component state; keep component-only state local with `ref`/`reactive`.
98+
- Prefer **setup stores**: `defineStore('user', () => { const user = ref(...); const isLoggedIn = computed(...); function login(){}; return { user, isLoggedIn, login } })`.
99+
- One store per domain; keep actions for async/side effects and getters pure & synchronous.
100+
- Destructure with `storeToRefs()` to preserve reactivity; use `$patch` for batched mutations, `$reset` to restore state, and `$subscribe`/`$onAction` for cross-cutting concerns.
101+
- Handle SSR hydration correctly and keep stores serializable.
102+
103+
## Routing with Vue Router
104+
- Define routes with lazy `component: () => import('...')` for automatic code splitting.
105+
- Use navigation guards (`beforeEach`, `beforeEnter`, `beforeRouteLeave`) for auth and unsaved-changes checks; always resolve/`next()` exactly once.
106+
- Use `route.meta` (typed) for per-route config like `requiresAuth`.
107+
- Read params/query via `useRoute()` and navigate via `useRouter()`; treat `route.params` as reactive (watch it, don't cache).
108+
- Configure `scrollBehavior` for predictable scroll restoration; enable typed routes where available.
109+
110+
## TypeScript Integration
111+
- Type props/emits/slots through generic compiler macros, not runtime object syntax.
112+
- Type refs explicitly when inference is too narrow: `ref<User | null>(null)`.
113+
- Type template refs with `useTemplateRef<HTMLInputElement>('input')` (3.5+) or `ref<HTMLInputElement | null>(null)`.
114+
- Build generic components with `<script setup lang="ts" generic="T">`.
115+
- Type provide/inject with `InjectionKey<T>`; type Pinia stores via their inferred return types.
116+
117+
## Styling
118+
- Default to `<style scoped>`; use `:deep()`, `:slotted()`, and `:global()` selectors deliberately.
119+
- Use `v-bind()` in `<style>` to drive CSS from reactive state; prefer CSS custom properties for theming.
120+
- Consider CSS Modules (`<style module>`) for class-name isolation in larger teams.
121+
122+
## Forms & Validation
123+
- Bind inputs with `v-model` (and `defineModel` for custom inputs); use modifiers `.lazy`, `.number`, `.trim`.
124+
- Validate with a schema library (Zod/Yup) plus a form library (VeeValidate or FormKit) for non-trivial forms.
125+
- Client validation is for UX only — always validate and sanitize on the server.
126+
127+
## Error Handling
128+
- Use `onErrorCaptured` for component-tree boundaries and `app.config.errorHandler` for a global hook.
129+
- Wrap async/lazy boundaries with `<Suspense>` + an error fallback.
130+
- Surface user-friendly errors; log diagnostics to your monitoring pipeline.
131+
132+
## Performance
133+
- Code-split routes and heavy components (`defineAsyncComponent`, dynamic `import()`).
134+
- Use `computed` for caching, `v-memo`/`v-once` for static subtrees, and `shallowRef`/`shallowReactive` for big datasets.
135+
- Virtualize long lists (e.g. `vue-virtual-scroller`); paginate or window large data.
136+
- Avoid unnecessary deep reactivity and avoid creating new object/array literals inline in templates.
137+
- In 3.5+, consider lazy hydration strategies for SSR to reduce time-to-interactive.
138+
139+
## SSR / Meta-frameworks
140+
- Prefer Nuxt for SSR/SSG/hybrid rendering unless you have a reason to hand-roll SSR.
141+
- Keep code isomorphic: guard browser APIs, avoid module-level shared mutable state across requests, and ensure stores are request-scoped.
142+
- Match server and client output to prevent hydration mismatches.
143+
144+
## Accessibility
145+
- Use semantic HTML first; add ARIA only to fill genuine gaps.
146+
- Ensure full keyboard operability and visible focus states.
147+
- Manage focus on route changes and when opening/closing dialogs (trap focus in modals).
148+
- Give icon-only controls accessible names (`aria-label`); associate labels with inputs.
149+
150+
## Security
151+
- Never render untrusted input with `v-html`; sanitize (e.g. DOMPurify) if it is unavoidable.
152+
- Avoid dynamic `:is`/`:href`/`:src` from untrusted sources; validate URLs (block `javascript:` schemes).
153+
- Keep secrets server-side; only expose `VITE_`-prefixed env vars intentionally meant to be public.
154+
- Apply a Content Security Policy and standard CSRF/XSS protections at the app layer.
155+
156+
## Testing
157+
- Unit-test composables as plain functions; component-test with Vue Test Utils / Testing Library.
158+
- Test observable behavior and rendered output, not internal implementation details.
159+
- Mock stores with `createTestingPinia`; stub router and async boundaries as needed.
160+
- Cover critical user journeys with end-to-end tests (Playwright or Cypress).
161+
162+
## Tooling
163+
- Use Vite with the official Vue plugin; enable `vue-tsc` for type-checking in CI.
164+
- Use ESLint (`eslint-plugin-vue`) and Prettier; enable Volar/Vue official extension for the best DX.
165+
- Manage env via `import.meta.env` with `VITE_`-prefixed variables.
166+
167+
## Anti-Patterns to Avoid
168+
- Mixing Options API and Composition API arbitrarily in the same codebase.
169+
- Mutating props directly, or destructuring `reactive()`/Pinia stores without `toRefs`/`storeToRefs`.
170+
- Using `watch` for values that should be `computed`.
171+
- `v-if` together with `v-for` on one element; using array index as `:key`.
172+
- Heavy logic inside templates; unbounded deep reactivity on large data.
173+
- Leaking timers/listeners by skipping `onUnmounted` cleanup.
174+
- Rendering untrusted HTML via `v-html`.

0 commit comments

Comments
 (0)