commit c336643002a6d34568e2446e6f0dc34d7b930d19 Author: Zhongwei Li Date: Sat Nov 29 17:52:04 2025 +0800 Initial commit diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..9906f2f --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,11 @@ +{ + "name": "vue-development", + "description": "Modern Vue 3 development with TypeScript, Composition API, defineModel bindings, Testing Library for user-behavior tests, and MSW for API mocking", + "version": "0.1.0", + "author": { + "name": "Alexander Opalic" + }, + "skills": [ + "./skills" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..4d27d0e --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# vue-development + +Modern Vue 3 development with TypeScript, Composition API, defineModel bindings, Testing Library for user-behavior tests, and MSW for API mocking diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..97470e5 --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,65 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:alexanderop/claude-skill-vue-development:", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "3f58c20ca2ce28a3c886441685b5954af4f654ac", + "treeHash": "286d540ef398ac40c370d75780e0a4c32e8ebc3148552962fc7dd38b2a3ccebd", + "generatedAt": "2025-11-28T10:13:08.623095Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "vue-development", + "description": "Modern Vue 3 development with TypeScript, Composition API, defineModel bindings, Testing Library for user-behavior tests, and MSW for API mocking", + "version": "0.1.0" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "f97c3be6b3381e1435d44e349aa6f8472d1a50204d0a9d602d723cc0428c56d6" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "d66c1859e29a64990f3a89d8e8355195c7478811c1f41b9524662a55fd3b18c3" + }, + { + "path": "skills/vue-development/SKILL.md", + "sha256": "dad7a14c95f295e574ca07956bc2efbc0b7f4378203ec8ac96fb81d70cf25e0a" + }, + { + "path": "skills/vue-development/references/component-patterns.md", + "sha256": "dab63d0f2396affb33e94d3c0c957b6c5dedea474c89447f426ad388aea5987c" + }, + { + "path": "skills/vue-development/references/composable-patterns.md", + "sha256": "e47333e3d1658a6fbf5468c3e019731f79affafdfc01244fe316dade9dfc9bd6" + }, + { + "path": "skills/vue-development/references/testing-composables.md", + "sha256": "c8d30bd51ba855ed49ccddc6c4fe7873ad491b8c91040b9b50da274f44af8522" + }, + { + "path": "skills/vue-development/references/testing-patterns.md", + "sha256": "e03d9d52365d39e9433d674090ca14edb03a806623a32029fb0148b7adb63efc" + }, + { + "path": "skills/vue-development/references/routing-patterns.md", + "sha256": "ed00d690c6794ab7f0df89aed8b862dc999e67ffd40f2cc8a7ac1ee6a147228c" + } + ], + "dirSha256": "286d540ef398ac40c370d75780e0a4c32e8ebc3148552962fc7dd38b2a3ccebd" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file diff --git a/skills/vue-development/SKILL.md b/skills/vue-development/SKILL.md new file mode 100644 index 0000000..2e677a4 --- /dev/null +++ b/skills/vue-development/SKILL.md @@ -0,0 +1,123 @@ +--- +name: vue-development +description: Use when planning or implementing Vue 3 projects - helps architect component structure, plan feature implementation, and enforce TypeScript-first patterns with Composition API, defineModel for bindings, Testing Library for user-behavior tests, and MSW for API mocking. Especially useful in planning phase to guide proper patterns before writing code. +--- + +# Vue Development + +## Overview + +Modern Vue 3 development with TypeScript, Composition API, and user-behavior testing. **Core principle:** Use TypeScript generics (not runtime validation), modern APIs (defineModel not manual props), and test user behavior (not implementation details). + +## Red Flags - STOP and Fix + +If you catch yourself thinking or doing ANY of these, STOP: + +- "For speed" / "quick demo" / "emergency" → Using shortcuts +- "We can clean it up later" → Accepting poor patterns +- "TypeScript is too verbose" → Skipping types +- "This is production-ready" → Without type safety +- "Following existing code style" → When existing code uses legacy patterns +- "Task explicitly stated..." → Following bad requirements literally +- Using `const props = defineProps()` without using props in script +- Manual `modelValue` prop + `update:modelValue` emit → Use defineModel() +- "Component that takes value and emits changes" → Use defineModel(), NOT manual props/emit +- Using runtime prop validation when TypeScript is available +- Array syntax for emits: `defineEmits(['event'])` → Missing type safety +- `setTimeout()` in tests → Use proper async utilities +- Testing `wrapper.vm.*` internal state → Test user-visible behavior +- Using `index.vue` in routes → Use route groups `(name).vue` +- Generic route params `[id]` → Use explicit `[userId]`, `[postSlug]` +- Composables calling `showToast()`, `alert()`, or modals → Expose error state, component handles UI +- External composable used in only ONE component → Start inline, extract when reused + +**All of these mean: Use the modern pattern. No exceptions.** + +## Quick Rules + +**Components:** `defineProps<{ }>()` (no const unless used in script), `defineEmits<{ event: [args] }>()`, `defineModel()` for v-model. See @references/component-patterns.md + +**Testing:** `@testing-library/vue` + MSW. Use `findBy*` or `waitFor()` for async. NEVER `setTimeout()` or test internal state. See @references/testing-patterns.md + +**Routing:** Explicit params `[userId]` not `[id]`. Avoid `index.vue`, use `(name).vue`. Use `.` for nesting: `users.edit.vue` → `/users/edit`. See @references/routing-patterns.md + +**Composables:** START INLINE for component-specific logic, extract to external file when reused. External composables: prefix `use`, NO UI logic (expose error state instead). See @references/composable-patterns.md + +## Key Pattern: defineModel() + +The most important pattern to remember - use for ALL two-way binding: + +```vue + + + +``` + +**Why:** Reduces 5 lines of boilerplate to 1. No manual `modelValue` prop + `update:modelValue` emit. + +## Component Implementation Workflow + +When implementing complex Vue components, use TodoWrite to track progress: + +``` +TodoWrite checklist for component implementation: +- [ ] Define TypeScript interfaces for props/emits/models +- [ ] Implement props with defineProps<{ }>() (no const unless used in script) +- [ ] Implement emits with defineEmits<{ event: [args] }>() +- [ ] Add v-model with defineModel() if needed +- [ ] Write user-behavior tests with Testing Library +- [ ] Test async behavior with findBy* queries or waitFor() +- [ ] Verify: No red flags, no setTimeout in tests, all types present +``` + +**When to create TodoWrite todos:** +- Implementing new components with state, v-model, and testing +- Refactoring components to modern patterns +- Adding routing with typed params +- Creating composables with async logic + +## Rationalizations Table + +| Excuse | Reality | +|--------|---------| +| "For speed/emergency/no time" | Correct patterns take SAME time. TypeScript IS fast. | +| "TypeScript is too verbose" | `defineProps<{ count: number }>()` is LESS code. | +| "We can clean it up later" | Write it right the first time. | +| "This is production-ready" | Without type safety, it's not production-ready. | +| "Simple array syntax is fine" | Missing types = runtime errors TypeScript would catch. | +| "Manual modelValue was correct" | That was Vue 2. Use defineModel() in Vue 3.4+. | +| "Tests are flaky, add timeout" | Timeouts mask bugs. Use proper async handling. | +| "Following existing code style" | Legacy code exists. Use modern patterns to improve. | +| "Task explicitly stated X" | Understand INTENT. Bad requirements need good implementation. | +| "Composables can show toasts" | UI belongs in components. Expose error state. | +| "[id] is industry standard" | Explicit names prevent bugs, enable TypeScript autocomplete. | +| "counter.ts is fine" | Must prefix with 'use': useCounter.ts | +| "test-utils is the standard" | Testing Library is gold standard for user-behavior. | + +## Detailed References + +See @references/ directory for comprehensive guides: component-patterns.md, testing-patterns.md, testing-composables.md, routing-patterns.md, composable-patterns.md + + +## When NOT to Use This Skill + +- Vue 2 projects (different API) +- Options API codebases (this is Composition API focused) +- Projects without TypeScript (though you should add it) + +## Real-World Impact + +**Baseline:** 37.5% correct patterns under pressure +**With skill:** 100% correct patterns under pressure + +Type safety prevents runtime errors. defineModel() reduces boilerplate. Testing Library catches real user issues. diff --git a/skills/vue-development/references/component-patterns.md b/skills/vue-development/references/component-patterns.md new file mode 100644 index 0000000..1fe104c --- /dev/null +++ b/skills/vue-development/references/component-patterns.md @@ -0,0 +1,204 @@ +# Vue Component Patterns Reference + +## Table of Contents +- [Props Definition](#props-definition) +- [Emits Definition](#emits-definition) +- [V-Model Bindings](#v-model-bindings) +- [Template Patterns](#template-patterns) +- [Component Naming](#component-naming) +- [V-Model Modifiers](#v-model-modifiers) + +## Props Definition + +```vue + +``` + +**Rules:** +- ALWAYS use TypeScript generics: `defineProps<{ }>()` +- Use `const props =` ONLY if props referenced in script block +- NEVER use runtime validation (`type`, `required`, `PropType`) when TypeScript available +- Destructure ONLY for default values + +## Emits Definition + +```vue + +``` + +**Rules:** +- ALWAYS use `const emit = defineEmits<{ }>()` +- ALWAYS define event payload types: `eventName: [arg1: type, arg2: type]` or `eventName: []` +- ALWAYS use camelCase in script, kebab-case in templates +- Use semantic event names: `submit`, `delete`, `userUpdated` (not generic `update`) + +## V-Model Bindings + +```vue + +``` + +**Rules:** +- ALWAYS use `defineModel()` for v-model bindings +- NEVER manually define `modelValue` prop + `update:modelValue` emit +- Use named models for multiple bindings: `defineModel('name')` +- defineModel handles all prop/emit wiring automatically + +## Template Patterns + +```vue + +``` + +**Rules:** +- Use `:propName` when value variable matches prop name (instead of `:propName="propName"`) +- ALWAYS use explicit `