mdk-skills 2.2.2 → 2.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/.claude/.install.log +9 -40
  2. package/.claude/backups/20260510.151953/.install.log +1 -0
  3. package/package.json +1 -1
  4. package/scripts/web-ui/server.js +8 -1
  5. package/.claude/backups/20260510.145547/.install.log +0 -18
  6. package/.claude/backups/20260510.145547/settings.json +0 -35
  7. package/.claude/backups/20260510.145547/skills/test1/.meta.json +0 -6
  8. package/.claude/backups/20260510.145547/skills/test2/.meta.json +0 -6
  9. package/.claude/backups/20260510.145651/.install.log +0 -19
  10. package/.claude/backups/20260510.145651/profiles.json +0 -67
  11. package/.claude/backups/20260510.145651/skills/frontend-code-review/.meta.json +0 -6
  12. package/.claude/backups/20260510.145651/skills/frontend-code-review/SKILL.md +0 -167
  13. package/.claude/backups/20260510.145651/skills/frontend-code-review/references/checklist.md +0 -298
  14. package/.claude/backups/20260510.145651/skills/frontend-design/.meta.json +0 -6
  15. package/.claude/backups/20260510.145651/skills/frontend-design/LICENSE.txt +0 -177
  16. package/.claude/backups/20260510.145651/skills/frontend-design/SKILL.md +0 -42
  17. package/.claude/backups/20260510.145651/skills/skill-creator/.meta.json +0 -6
  18. package/.claude/backups/20260510.145651/skills/skill-creator/SKILL.md +0 -356
  19. package/.claude/backups/20260510.145651/skills/skill-creator/references/output-patterns.md +0 -82
  20. package/.claude/backups/20260510.145651/skills/skill-creator/references/workflows.md +0 -28
  21. package/.claude/backups/20260510.145651/skills/skill-creator/scripts/init_skill.py +0 -303
  22. package/.claude/backups/20260510.145651/skills/skill-creator/scripts/package_skill.py +0 -110
  23. package/.claude/backups/20260510.145651/skills/skill-creator/scripts/quick_validate.py +0 -95
  24. package/.claude/backups/20260510.145651/skills/test1/.meta.json +0 -6
  25. package/.claude/backups/20260510.145651/skills/test2/.meta.json +0 -6
  26. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/.meta.json +0 -6
  27. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/SKILL.md +0 -228
  28. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/charts.csv +0 -26
  29. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/colors.csv +0 -97
  30. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/landing.csv +0 -31
  31. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/products.csv +0 -97
  32. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/prompts.csv +0 -24
  33. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/stacks/flutter.csv +0 -53
  34. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +0 -56
  35. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/stacks/nextjs.csv +0 -53
  36. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +0 -51
  37. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +0 -59
  38. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/stacks/react-native.csv +0 -52
  39. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/stacks/react.csv +0 -54
  40. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/stacks/svelte.csv +0 -54
  41. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/stacks/swiftui.csv +0 -51
  42. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/stacks/vue.csv +0 -50
  43. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/styles.csv +0 -59
  44. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/typography.csv +0 -58
  45. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/data/ux-guidelines.csv +0 -100
  46. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/scripts/core.py +0 -238
  47. package/.claude/backups/20260510.145651/skills/ui-ux-pro-max/scripts/search.py +0 -61
  48. package/.claude/backups/20260510.145651/skills/v3-fe-biz-patterns/.meta.json +0 -6
  49. package/.claude/backups/20260510.145651/skills/v3-fe-biz-patterns/SKILL.md +0 -26
  50. package/.claude/backups/20260510.145651/skills/v3-fe-biz-patterns/references/infinite-scroll.md +0 -292
  51. package/.claude/backups/20260510.145651/skills/v3-fe-biz-patterns/references/pinia-store.md +0 -174
  52. package/.claude/backups/20260510.145651/skills/v3-fe-biz-patterns/references/service-layer.md +0 -198
  53. package/.claude/backups/20260510.145651/skills/v3-fe-biz-patterns/references/tab-anchor.md +0 -1125
  54. package/.claude/backups/20260510.145651/skills/v3-fe-biz-patterns/references/use-loading.md +0 -114
  55. package/.claude/backups/20260510.145651/skills/vue/.meta.json +0 -6
  56. package/.claude/backups/20260510.145651/skills/vue/SKILL.md +0 -103
  57. package/.claude/backups/20260510.145651/skills/vue/references/components.md +0 -323
  58. package/.claude/backups/20260510.145651/skills/vue/references/composables.md +0 -358
  59. package/.claude/backups/20260510.145651/skills/vue/references/directives.md +0 -225
  60. package/.claude/backups/20260510.145651/skills/vue/references/gotchas.md +0 -438
  61. package/.claude/backups/20260510.145651/skills/vue/references/provide-inject.md +0 -174
  62. package/.claude/backups/20260510.145651/skills/vue/references/reactivity.md +0 -289
  63. package/.claude/backups/20260510.145651/skills/vue/references/router.md +0 -181
  64. package/.claude/backups/20260510.145651/skills/vue/references/testing.md +0 -294
  65. package/.claude/backups/20260510.145651/skills/vue/references/typescript.md +0 -172
  66. package/.claude/backups/20260510.145651/skills/vue/references/utils-client.md +0 -156
  67. package/.claude/backups/20260510.150310/.install.log +0 -30
  68. package/.claude/backups/20260510.150310/profiles.json +0 -67
  69. package/.claude/backups/20260510.150310/settings.json +0 -29
  70. package/.claude/backups/20260510.150310/skills/frontend-code-review/.meta.json +0 -6
  71. package/.claude/backups/20260510.150310/skills/frontend-code-review/SKILL.md +0 -167
  72. package/.claude/backups/20260510.150310/skills/frontend-code-review/references/checklist.md +0 -298
  73. package/.claude/backups/20260510.150310/skills/frontend-design/.meta.json +0 -6
  74. package/.claude/backups/20260510.150310/skills/frontend-design/LICENSE.txt +0 -177
  75. package/.claude/backups/20260510.150310/skills/frontend-design/SKILL.md +0 -42
  76. package/.claude/backups/20260510.150310/skills/skill-creator/.meta.json +0 -6
  77. package/.claude/backups/20260510.150310/skills/skill-creator/SKILL.md +0 -356
  78. package/.claude/backups/20260510.150310/skills/skill-creator/references/output-patterns.md +0 -82
  79. package/.claude/backups/20260510.150310/skills/skill-creator/references/workflows.md +0 -28
  80. package/.claude/backups/20260510.150310/skills/skill-creator/scripts/init_skill.py +0 -303
  81. package/.claude/backups/20260510.150310/skills/skill-creator/scripts/package_skill.py +0 -110
  82. package/.claude/backups/20260510.150310/skills/skill-creator/scripts/quick_validate.py +0 -95
  83. package/.claude/backups/20260510.150310/skills/test1/.meta.json +0 -6
  84. package/.claude/backups/20260510.150310/skills/test2/.meta.json +0 -6
  85. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/.meta.json +0 -6
  86. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/SKILL.md +0 -228
  87. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/charts.csv +0 -26
  88. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/colors.csv +0 -97
  89. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/landing.csv +0 -31
  90. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/products.csv +0 -97
  91. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/prompts.csv +0 -24
  92. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/stacks/flutter.csv +0 -53
  93. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +0 -56
  94. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/stacks/nextjs.csv +0 -53
  95. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +0 -51
  96. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +0 -59
  97. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/stacks/react-native.csv +0 -52
  98. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/stacks/react.csv +0 -54
  99. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/stacks/svelte.csv +0 -54
  100. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/stacks/swiftui.csv +0 -51
  101. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/stacks/vue.csv +0 -50
  102. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/styles.csv +0 -59
  103. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/typography.csv +0 -58
  104. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/data/ux-guidelines.csv +0 -100
  105. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/scripts/core.py +0 -238
  106. package/.claude/backups/20260510.150310/skills/ui-ux-pro-max/scripts/search.py +0 -61
  107. package/.claude/backups/20260510.150310/skills/v3-fe-biz-patterns/.meta.json +0 -6
  108. package/.claude/backups/20260510.150310/skills/v3-fe-biz-patterns/SKILL.md +0 -26
  109. package/.claude/backups/20260510.150310/skills/v3-fe-biz-patterns/references/infinite-scroll.md +0 -292
  110. package/.claude/backups/20260510.150310/skills/v3-fe-biz-patterns/references/pinia-store.md +0 -174
  111. package/.claude/backups/20260510.150310/skills/v3-fe-biz-patterns/references/service-layer.md +0 -198
  112. package/.claude/backups/20260510.150310/skills/v3-fe-biz-patterns/references/tab-anchor.md +0 -1125
  113. package/.claude/backups/20260510.150310/skills/v3-fe-biz-patterns/references/use-loading.md +0 -114
  114. package/.claude/backups/20260510.150310/skills/vue/.meta.json +0 -6
  115. package/.claude/backups/20260510.150310/skills/vue/SKILL.md +0 -103
  116. package/.claude/backups/20260510.150310/skills/vue/references/components.md +0 -323
  117. package/.claude/backups/20260510.150310/skills/vue/references/composables.md +0 -358
  118. package/.claude/backups/20260510.150310/skills/vue/references/directives.md +0 -225
  119. package/.claude/backups/20260510.150310/skills/vue/references/gotchas.md +0 -438
  120. package/.claude/backups/20260510.150310/skills/vue/references/provide-inject.md +0 -174
  121. package/.claude/backups/20260510.150310/skills/vue/references/reactivity.md +0 -289
  122. package/.claude/backups/20260510.150310/skills/vue/references/router.md +0 -181
  123. package/.claude/backups/20260510.150310/skills/vue/references/testing.md +0 -294
  124. package/.claude/backups/20260510.150310/skills/vue/references/typescript.md +0 -172
  125. package/.claude/backups/20260510.150310/skills/vue/references/utils-client.md +0 -156
  126. package/.claude/backups/CLAUDE.md.20260510.145155 +0 -131
  127. package/.claude/backups/CLAUDE.md.20260510.145651 +0 -131
  128. package/.claude/backups/CLAUDE.md.20260510.150310 +0 -131
  129. package/.claude/skills/test1/.meta.json +0 -6
  130. package/.claude/skills/test2/.meta.json +0 -6
  131. /package/.claude/backups/{20260510.145547 → 20260510.151953}/profiles.json +0 -0
  132. /package/.claude/backups/{20260510.145651 → 20260510.151953}/settings.json +0 -0
  133. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/frontend-code-review/.meta.json +0 -0
  134. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/frontend-code-review/SKILL.md +0 -0
  135. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/frontend-code-review/references/checklist.md +0 -0
  136. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/frontend-design/.meta.json +0 -0
  137. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/frontend-design/LICENSE.txt +0 -0
  138. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/frontend-design/SKILL.md +0 -0
  139. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/skill-creator/.meta.json +0 -0
  140. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/skill-creator/SKILL.md +0 -0
  141. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/skill-creator/references/output-patterns.md +0 -0
  142. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/skill-creator/references/workflows.md +0 -0
  143. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/skill-creator/scripts/init_skill.py +0 -0
  144. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/skill-creator/scripts/package_skill.py +0 -0
  145. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/skill-creator/scripts/quick_validate.py +0 -0
  146. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/.meta.json +0 -0
  147. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/SKILL.md +0 -0
  148. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/charts.csv +0 -0
  149. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/colors.csv +0 -0
  150. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/landing.csv +0 -0
  151. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/products.csv +0 -0
  152. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/prompts.csv +0 -0
  153. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/stacks/flutter.csv +0 -0
  154. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +0 -0
  155. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/stacks/nextjs.csv +0 -0
  156. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +0 -0
  157. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +0 -0
  158. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/stacks/react-native.csv +0 -0
  159. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/stacks/react.csv +0 -0
  160. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/stacks/svelte.csv +0 -0
  161. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/stacks/swiftui.csv +0 -0
  162. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/stacks/vue.csv +0 -0
  163. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/styles.csv +0 -0
  164. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/typography.csv +0 -0
  165. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/data/ux-guidelines.csv +0 -0
  166. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/scripts/core.py +0 -0
  167. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/ui-ux-pro-max/scripts/search.py +0 -0
  168. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/v3-fe-biz-patterns/.meta.json +0 -0
  169. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/v3-fe-biz-patterns/SKILL.md +0 -0
  170. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/v3-fe-biz-patterns/references/infinite-scroll.md +0 -0
  171. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/v3-fe-biz-patterns/references/pinia-store.md +0 -0
  172. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/v3-fe-biz-patterns/references/service-layer.md +0 -0
  173. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/v3-fe-biz-patterns/references/tab-anchor.md +0 -0
  174. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/v3-fe-biz-patterns/references/use-loading.md +0 -0
  175. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/vue/.meta.json +0 -0
  176. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/vue/SKILL.md +0 -0
  177. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/vue/references/components.md +0 -0
  178. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/vue/references/composables.md +0 -0
  179. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/vue/references/directives.md +0 -0
  180. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/vue/references/gotchas.md +0 -0
  181. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/vue/references/provide-inject.md +0 -0
  182. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/vue/references/reactivity.md +0 -0
  183. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/vue/references/router.md +0 -0
  184. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/vue/references/testing.md +0 -0
  185. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/vue/references/typescript.md +0 -0
  186. /package/.claude/backups/{20260510.145547 → 20260510.151953}/skills/vue/references/utils-client.md +0 -0
  187. /package/.claude/backups/{CLAUDE.md.20260510.144501 → CLAUDE.md.20260510.151953} +0 -0
@@ -1,438 +0,0 @@
1
- # Vue Common Gotchas & Edge Cases
2
-
3
- Critical Vue 3 gotchas that cause silent failures or hard-to-debug issues.
4
-
5
- > Based on [vuejs-ai/skills](https://github.com/vuejs-ai/skills) vue-best-practices. For comprehensive coverage (200+ rules), see the upstream repo.
6
-
7
- ## Reactivity
8
-
9
- ### Always Use `.value` When Accessing ref() in Scripts
10
-
11
- **Impact: HIGH** - Forgetting `.value` causes silent failures.
12
-
13
- ```ts
14
- const count = ref(0)
15
-
16
- // WRONG
17
- count++ // Tries to increment the ref object
18
- count = 5 // Reassigns variable, loses reactivity
19
- items.push(4) // Error: push is not a function
20
-
21
- // CORRECT
22
- count.value++
23
- count.value = 5
24
- items.value.push(4)
25
-
26
- // In templates - NO .value needed (Vue unwraps automatically)
27
- // {{ count }} works, not {{ count.value }}
28
- ```
29
-
30
- ### Never Destructure reactive() Objects Directly
31
-
32
- **Impact: HIGH** - Destructuring breaks reactive connection.
33
-
34
- ```ts
35
- const state = reactive({ count: 0, name: 'Vue' })
36
-
37
- // WRONG - destructured variables lose reactivity
38
- const { count, name } = state
39
- state.count++
40
- console.log(count) // Still 0!
41
-
42
- // CORRECT - use toRefs()
43
- const { count, name } = toRefs(state)
44
- state.count++
45
- console.log(count.value) // 1
46
-
47
- // BEST - just use ref() instead of reactive()
48
- const count = ref(0)
49
- const name = ref('Vue')
50
- ```
51
-
52
- ### Proxy Identity Hazard with reactive()
53
-
54
- ```ts
55
- const raw = {}
56
- const proxy = reactive(raw)
57
-
58
- // WRONG - comparing different objects
59
- console.log(proxy === raw) // false
60
-
61
- // WRONG - creating multiple proxies
62
- const a = reactive({})
63
- const b = reactive(a) // Returns same proxy
64
- console.log(a === b) // true (same object)
65
-
66
- // GOTCHA - nested objects get proxied too
67
- const nested = reactive({ obj: {} })
68
- console.log(nested.obj === nested.obj) // true (same proxy)
69
- ```
70
-
71
- ## Computed Properties
72
-
73
- ### No Side Effects in Computed Getters
74
-
75
- **Impact: HIGH** - Side effects break reactivity model.
76
-
77
- ```ts
78
- // WRONG - mutates state
79
- const doubled = computed(() => {
80
- count.value++ // Side effect!
81
- return count.value * 2
82
- })
83
-
84
- // WRONG - async operation
85
- const data = computed(async () => {
86
- return await fetch('/api') // Side effect!
87
- })
88
-
89
- // CORRECT - pure computation only
90
- const doubled = computed(() => count.value * 2)
91
-
92
- // For side effects, use watch:
93
- watch(count, (newVal) => {
94
- document.title = `Count: ${newVal}`
95
- })
96
- ```
97
-
98
- ### Computed Returns Are Read-Only
99
-
100
- ```ts
101
- const fullName = computed(() => `${first.value} ${last.value}`)
102
-
103
- // WRONG - computed values are read-only
104
- fullName.value = 'John Doe' // Error!
105
-
106
- // CORRECT - use writable computed
107
- const fullName = computed({
108
- get: () => `${first.value} ${last.value}`,
109
- set: (val) => {
110
- const [f, l] = val.split(' ')
111
- first.value = f
112
- last.value = l
113
- }
114
- })
115
- ```
116
-
117
- ## Watchers
118
-
119
- ### Clean Up Async Operations to Prevent Race Conditions
120
-
121
- **Impact: HIGH** - Stale requests can overwrite newer data.
122
-
123
- ```ts
124
- const query = ref('')
125
- const results = ref([])
126
-
127
- // WRONG - race condition
128
- watch(query, async (q) => {
129
- const res = await fetch(`/api?q=${q}`)
130
- results.value = await res.json() // May overwrite newer results!
131
- })
132
-
133
- // CORRECT - use onWatcherCleanup (Vue 3.5+)
134
- watch(query, async (q) => {
135
- const controller = new AbortController()
136
- onWatcherCleanup(() => controller.abort())
137
-
138
- try {
139
- const res = await fetch(`/api?q=${q}`, { signal: controller.signal })
140
- results.value = await res.json()
141
- } catch (e) {
142
- if (e.name !== 'AbortError') throw e
143
- }
144
- })
145
-
146
- // Or use onCleanup parameter
147
- watch(query, async (q, oldQ, onCleanup) => {
148
- const controller = new AbortController()
149
- onCleanup(() => controller.abort())
150
- // ... same as above
151
- })
152
- ```
153
-
154
- ### Deep Watch Returns Same Object Reference
155
-
156
- ```ts
157
- const obj = reactive({ nested: { count: 0 } })
158
-
159
- // GOTCHA - oldValue === newValue for deep watches
160
- watch(obj, (newVal, oldVal) => {
161
- console.log(newVal === oldVal) // true! Same object
162
- }, { deep: true })
163
-
164
- // If you need old value, clone first:
165
- watch(
166
- () => structuredClone(obj),
167
- (newVal, oldVal) => { /* now different */ }
168
- )
169
- ```
170
-
171
- ## Props
172
-
173
- ### Props Are Read-Only - Never Mutate
174
-
175
- **Impact: HIGH** - Breaks one-way data flow.
176
-
177
- ```ts
178
- const props = defineProps<{ count: number; user: User }>()
179
-
180
- // WRONG - direct mutation
181
- props.count++ // Vue warning
182
- props.user.name = 'New' // No warning but still wrong!
183
-
184
- // CORRECT - emit to parent
185
- const emit = defineEmits(['update:count', 'update-user'])
186
- emit('update:count', props.count + 1)
187
- emit('update-user', { ...props.user, name: 'New' })
188
-
189
- // Or create local copy
190
- const localUser = ref({ ...props.user })
191
- ```
192
-
193
- ### Destructured Props Don't Update Watchers (pre-3.5)
194
-
195
- ```ts
196
- // WRONG (Vue < 3.5)
197
- const { count } = defineProps<{ count: number }>()
198
- watch(count, () => {}) // Won't trigger!
199
-
200
- // CORRECT - use getter
201
- const props = defineProps<{ count: number }>()
202
- watch(() => props.count, () => {})
203
-
204
- // Vue 3.5+ - destructuring works with reactive props
205
- const { count } = defineProps<{ count: number }>()
206
- watch(() => count, () => {}) // Works in 3.5+
207
- ```
208
-
209
- ## Lifecycle Hooks
210
-
211
- ### Register Hooks Synchronously During Setup
212
-
213
- **Impact: HIGH** - Async hooks silently fail.
214
-
215
- ```ts
216
- // WRONG - hook registered after await
217
- async setup() {
218
- const data = await fetchData()
219
- onMounted(() => {}) // Will NEVER run!
220
- }
221
-
222
- // WRONG - hook in setTimeout
223
- setup() {
224
- setTimeout(() => {
225
- onMounted(() => {}) // Will NEVER run!
226
- }, 100)
227
- }
228
-
229
- // CORRECT - register synchronously, async inside
230
- setup() {
231
- onMounted(async () => {
232
- const data = await fetchData()
233
- })
234
- }
235
- ```
236
-
237
- ## Templates
238
-
239
- ### Never Use v-if with v-for on Same Element
240
-
241
- **Impact: HIGH** - Vue 2/3 precedence differs.
242
-
243
- ```vue
244
- <!-- WRONG - ambiguous precedence -->
245
- <li v-for="user in users" v-if="user.active" :key="user.id">
246
-
247
- <!-- Vue 3: v-if runs FIRST, 'user' undefined! -->
248
-
249
- <!-- CORRECT - computed filter -->
250
- <li v-for="user in activeUsers" :key="user.id">
251
-
252
- <script setup>
253
- const activeUsers = computed(() => users.filter(u => u.active))
254
- </script>
255
-
256
- <!-- CORRECT - template wrapper -->
257
- <template v-for="user in users" :key="user.id">
258
- <li v-if="user.active">{{ user.name }}</li>
259
- </template>
260
- ```
261
-
262
- ### Template Refs Are Null with v-if
263
-
264
- ```ts
265
- const inputRef = ref<HTMLInputElement | null>(null)
266
-
267
- // GOTCHA - ref is null when element hidden
268
- <input v-if="show" ref="inputRef" />
269
-
270
- // WRONG - may be null
271
- inputRef.value.focus() // Error if !show
272
-
273
- // CORRECT - null check
274
- inputRef.value?.focus()
275
-
276
- // Or use watchEffect with flush: 'post'
277
- watchEffect(() => {
278
- inputRef.value?.focus()
279
- }, { flush: 'post' })
280
- ```
281
-
282
- ## defineModel
283
-
284
- ### Object Mutations Don't Emit
285
-
286
- ```ts
287
- const model = defineModel<{ name: string }>()
288
-
289
- // WRONG - mutation doesn't notify parent
290
- model.value.name = 'New' // Parent won't know!
291
-
292
- // CORRECT - replace entire object
293
- model.value = { ...model.value, name: 'New' }
294
- ```
295
-
296
- ### Updated Value Needs nextTick
297
-
298
- ```ts
299
- const model = defineModel<string>()
300
-
301
- // WRONG - value not updated yet
302
- model.value = 'new'
303
- console.log(model.value) // Still old value!
304
-
305
- // CORRECT - wait for nextTick
306
- model.value = 'new'
307
- await nextTick()
308
- console.log(model.value) // Now 'new'
309
- ```
310
-
311
- ## Component Events
312
-
313
- ### Undeclared Emits Can Fire Twice
314
-
315
- ```ts
316
- // WRONG - missing emit declaration causes double firing
317
- const emit = defineEmits([]) // 'click' not declared
318
- <button @click="emit('click')"> // Fires twice!
319
-
320
- // CORRECT - declare all custom events
321
- const emit = defineEmits(['click'])
322
- ```
323
-
324
- ### Events Don't Bubble Through Components
325
-
326
- ```vue
327
- <!-- Parent can't listen to grandchild events directly -->
328
- <Grandparent>
329
- <Parent>
330
- <Child @custom="handler" /> <!-- Only Parent can listen -->
331
- </Parent>
332
- </Grandparent>
333
-
334
- <!-- Solution: re-emit or use provide/inject -->
335
- ```
336
-
337
- ## Provide/Inject
338
-
339
- ### Reactivity Not Automatic
340
-
341
- ```ts
342
- // Provider
343
- const count = ref(0)
344
- provide('count', count) // Pass the ref, not .value
345
-
346
- // Consumer
347
- const count = inject('count') // Receives the ref
348
- console.log(count.value) // Reactive!
349
-
350
- // WRONG - loses reactivity
351
- provide('count', count.value) // Just passes number
352
- ```
353
-
354
- ### Must Call Provide Synchronously
355
-
356
- ```ts
357
- // WRONG - provide after async
358
- async setup() {
359
- await fetchData()
360
- provide('key', value) // Silently fails!
361
- }
362
-
363
- // CORRECT
364
- setup() {
365
- provide('key', value) // Synchronous
366
- onMounted(async () => {
367
- await fetchData()
368
- })
369
- }
370
- ```
371
-
372
- ## SSR
373
-
374
- ### Lifecycle Hooks Don't Run on Server
375
-
376
- ```ts
377
- // onMounted, onUpdated, onUnmounted - client only
378
- onMounted(() => {
379
- // Only runs in browser
380
- window.addEventListener('resize', handler)
381
- })
382
-
383
- // For SSR, use onServerPrefetch for data
384
- onServerPrefetch(async () => {
385
- data.value = await fetchData()
386
- })
387
- ```
388
-
389
- ### Hydration Mismatch Causes
390
-
391
- Common causes:
392
-
393
- - Browser-only APIs (`window`, `localStorage`)
394
- - Different timestamps
395
- - Random values
396
- - User-agent specific rendering
397
-
398
- ```ts
399
- // WRONG
400
- const width = ref(window.innerWidth) // undefined on server
401
-
402
- // CORRECT
403
- const width = ref(0)
404
- onMounted(() => {
405
- width.value = window.innerWidth
406
- })
407
- ```
408
-
409
- ## Performance
410
-
411
- ### Use shallowRef for Large Non-Reactive Data
412
-
413
- ```ts
414
- // WRONG - deep reactivity overhead
415
- const hugeList = ref(thousandsOfItems)
416
-
417
- // CORRECT - only track .value assignment
418
- const hugeList = shallowRef(thousandsOfItems)
419
-
420
- // Trigger update by replacing entire array
421
- hugeList.value = [...hugeList.value, newItem]
422
- ```
423
-
424
- ### markRaw for Non-Reactive Objects
425
-
426
- ```ts
427
- // WRONG - Chart.js instance becomes reactive (breaks it)
428
- const chart = ref(new Chart(ctx, config))
429
-
430
- // CORRECT - mark as non-reactive
431
- const chart = ref(markRaw(new Chart(ctx, config)))
432
- ```
433
-
434
- ## References
435
-
436
- - [vuejs-ai/skills vue-best-practices](https://github.com/vuejs-ai/skills/tree/main/skills/vue-best-practices) - Full 200+ rules
437
- - [Vue Style Guide](https://vuejs.org/style-guide/)
438
- - [Vue 3 Migration Guide](https://v3-migration.vuejs.org/)
@@ -1,174 +0,0 @@
1
- ---
2
- name: Provide / Inject
3
- description: Pass data through component tree without prop drilling
4
- ---
5
-
6
- # Provide / Inject
7
-
8
- Provide data from ancestor components to any descendant, avoiding prop drilling.
9
-
10
- ## Basic Usage
11
-
12
- ```vue
13
- <!-- Provider.vue -->
14
- <script setup lang="ts">
15
- import { provide, ref } from 'vue'
16
-
17
- const message = ref('hello')
18
- provide('message', message)
19
- </script>
20
- ```
21
-
22
- ```vue
23
- <!-- DeepChild.vue (any level deep) -->
24
- <script setup lang="ts">
25
- import { inject } from 'vue'
26
-
27
- const message = inject('message')
28
- </script>
29
- ```
30
-
31
- ## Typing with InjectionKey
32
-
33
- Use `InjectionKey` for type safety between provider and injector:
34
-
35
- ```ts
36
- // keys.ts
37
- import type { InjectionKey, Ref } from 'vue'
38
-
39
- export const messageKey = Symbol() as InjectionKey<Ref<string>>
40
- export const countKey = Symbol() as InjectionKey<number>
41
- ```
42
-
43
- ```vue
44
- <!-- Provider.vue -->
45
- <script setup lang="ts">
46
- import { provide, ref } from 'vue'
47
- import { messageKey } from './keys'
48
-
49
- const message = ref('hello')
50
- provide(messageKey, message)
51
- </script>
52
- ```
53
-
54
- ```vue
55
- <!-- Injector.vue -->
56
- <script setup lang="ts">
57
- import { inject } from 'vue'
58
- import { messageKey } from './keys'
59
-
60
- const message = inject(messageKey) // Ref<string> | undefined
61
- </script>
62
- ```
63
-
64
- ## Default Values
65
-
66
- ```ts
67
- // Simple default
68
- const value = inject('message', 'default value')
69
-
70
- // Factory function (for expensive defaults)
71
- const value = inject('key', () => new ExpensiveClass(), true)
72
- // ^ treat as factory
73
- ```
74
-
75
- ## App-Level Provide
76
-
77
- Available to all components:
78
-
79
- ```ts
80
- // main.ts
81
- import { createApp } from 'vue'
82
-
83
- const app = createApp(App)
84
- app.provide('globalConfig', { theme: 'dark' })
85
- ```
86
-
87
- ## Reactive Provide/Inject
88
-
89
- Provide reactive values for automatic updates:
90
-
91
- ```vue
92
- <!-- Provider.vue -->
93
- <script setup lang="ts">
94
- import { provide, ref } from 'vue'
95
-
96
- const count = ref(0)
97
- provide('count', count)
98
- </script>
99
- ```
100
-
101
- The injected value maintains reactivity connection.
102
-
103
- ## Mutations Best Practice
104
-
105
- Keep mutations in the provider, expose update functions:
106
-
107
- ```vue
108
- <!-- Provider.vue -->
109
- <script setup lang="ts">
110
- import { provide, ref, readonly } from 'vue'
111
-
112
- const location = ref('North Pole')
113
-
114
- function updateLocation(newLocation: string) {
115
- location.value = newLocation
116
- }
117
-
118
- provide('location', {
119
- location: readonly(location), // Prevent direct mutation
120
- updateLocation
121
- })
122
- </script>
123
- ```
124
-
125
- ```vue
126
- <!-- Injector.vue -->
127
- <script setup lang="ts">
128
- import { inject } from 'vue'
129
-
130
- const { location, updateLocation } = inject('location')!
131
- </script>
132
-
133
- <template>
134
- <button @click="updateLocation('South Pole')">
135
- {{ location }}
136
- </button>
137
- </template>
138
- ```
139
-
140
- ## Using Symbol Keys
141
-
142
- Recommended for libraries and large apps to avoid collisions:
143
-
144
- ```ts
145
- // keys.ts
146
- export const myKey = Symbol('myKey')
147
-
148
- // provider
149
- provide(myKey, value)
150
-
151
- // injector
152
- inject(myKey)
153
- ```
154
-
155
- ## Type Helpers
156
-
157
- ```ts
158
- // String key with explicit type
159
- const foo = inject<string>('foo')
160
- // ^? string | undefined
161
-
162
- // With default (removes undefined)
163
- const foo = inject<string>('foo', 'default')
164
- // ^? string
165
-
166
- // Force non-undefined (use when certain it's provided)
167
- const foo = inject('foo') as string
168
- ```
169
-
170
- <!--
171
- Source references:
172
- - https://vuejs.org/guide/components/provide-inject.html
173
- - https://vuejs.org/guide/typescript/composition-api.html#typing-provide-inject
174
- -->