@pythoughts/vue-skills-mcp 0.1.0

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 (208) hide show
  1. package/README.md +63 -0
  2. package/index.mjs +139 -0
  3. package/package.json +34 -0
  4. package/skills/create-adaptable-composable/SKILL.md +76 -0
  5. package/skills/vue-best-practices/SKILL.md +154 -0
  6. package/skills/vue-best-practices/references/animation-class-based-technique.md +254 -0
  7. package/skills/vue-best-practices/references/animation-state-driven-technique.md +291 -0
  8. package/skills/vue-best-practices/references/component-async.md +97 -0
  9. package/skills/vue-best-practices/references/component-data-flow.md +350 -0
  10. package/skills/vue-best-practices/references/component-fallthrough-attrs.md +174 -0
  11. package/skills/vue-best-practices/references/component-keep-alive.md +137 -0
  12. package/skills/vue-best-practices/references/component-slots.md +216 -0
  13. package/skills/vue-best-practices/references/component-suspense.md +228 -0
  14. package/skills/vue-best-practices/references/component-teleport.md +108 -0
  15. package/skills/vue-best-practices/references/component-transition-group.md +128 -0
  16. package/skills/vue-best-practices/references/component-transition.md +125 -0
  17. package/skills/vue-best-practices/references/composables.md +290 -0
  18. package/skills/vue-best-practices/references/directives.md +162 -0
  19. package/skills/vue-best-practices/references/perf-avoid-component-abstraction-in-lists.md +159 -0
  20. package/skills/vue-best-practices/references/perf-v-once-v-memo-directives.md +182 -0
  21. package/skills/vue-best-practices/references/perf-virtualize-large-lists.md +187 -0
  22. package/skills/vue-best-practices/references/plugins.md +166 -0
  23. package/skills/vue-best-practices/references/reactivity.md +346 -0
  24. package/skills/vue-best-practices/references/render-functions.md +201 -0
  25. package/skills/vue-best-practices/references/sfc.md +310 -0
  26. package/skills/vue-best-practices/references/state-management.md +135 -0
  27. package/skills/vue-best-practices/references/updated-hook-performance.md +187 -0
  28. package/skills/vue-debug-guides/SKILL.md +205 -0
  29. package/skills/vue-debug-guides/reference/animation-key-for-rerender.md +160 -0
  30. package/skills/vue-debug-guides/reference/animation-transitiongroup-performance.md +241 -0
  31. package/skills/vue-debug-guides/reference/async-component-error-handling.md +115 -0
  32. package/skills/vue-debug-guides/reference/async-component-keepalive-ref-issue.md +112 -0
  33. package/skills/vue-debug-guides/reference/async-component-suspense-control.md +84 -0
  34. package/skills/vue-debug-guides/reference/async-component-vue-router.md +109 -0
  35. package/skills/vue-debug-guides/reference/attrs-event-listener-merging.md +205 -0
  36. package/skills/vue-debug-guides/reference/checkbox-true-false-value-form-submission.md +118 -0
  37. package/skills/vue-debug-guides/reference/cleanup-side-effects.md +172 -0
  38. package/skills/vue-debug-guides/reference/click-events-on-components.md +180 -0
  39. package/skills/vue-debug-guides/reference/component-naming-conflicts.md +159 -0
  40. package/skills/vue-debug-guides/reference/component-ref-requires-defineexpose.md +176 -0
  41. package/skills/vue-debug-guides/reference/composable-avoid-hidden-side-effects.md +208 -0
  42. package/skills/vue-debug-guides/reference/composable-call-location-restrictions.md +141 -0
  43. package/skills/vue-debug-guides/reference/composable-naming-return-pattern.md +139 -0
  44. package/skills/vue-debug-guides/reference/composable-tovalue-inside-watcheffect.md +182 -0
  45. package/skills/vue-debug-guides/reference/composition-api-not-functional-programming.md +120 -0
  46. package/skills/vue-debug-guides/reference/composition-api-script-setup-async-context.md +203 -0
  47. package/skills/vue-debug-guides/reference/composition-api-vs-react-hooks-differences.md +156 -0
  48. package/skills/vue-debug-guides/reference/computed-array-mutation.md +148 -0
  49. package/skills/vue-debug-guides/reference/computed-conditional-dependencies.md +147 -0
  50. package/skills/vue-debug-guides/reference/computed-no-parameters.md +159 -0
  51. package/skills/vue-debug-guides/reference/computed-no-side-effects.md +107 -0
  52. package/skills/vue-debug-guides/reference/computed-return-value-readonly.md +160 -0
  53. package/skills/vue-debug-guides/reference/configure-app-before-mount.md +89 -0
  54. package/skills/vue-debug-guides/reference/declare-emits-for-documentation.md +212 -0
  55. package/skills/vue-debug-guides/reference/define-expose-before-await.md +192 -0
  56. package/skills/vue-debug-guides/reference/define-model-default-value-sync.md +139 -0
  57. package/skills/vue-debug-guides/reference/defineEmits-must-be-top-level.md +164 -0
  58. package/skills/vue-debug-guides/reference/defineEmits-no-runtime-and-type-mixed.md +170 -0
  59. package/skills/vue-debug-guides/reference/definemodel-object-mutation-no-emit.md +148 -0
  60. package/skills/vue-debug-guides/reference/dom-update-timing-nexttick.md +90 -0
  61. package/skills/vue-debug-guides/reference/dynamic-argument-constraints.md +146 -0
  62. package/skills/vue-debug-guides/reference/dynamic-component-registration-vite.md +147 -0
  63. package/skills/vue-debug-guides/reference/event-modifier-order-matters.md +101 -0
  64. package/skills/vue-debug-guides/reference/exact-modifier-for-precise-shortcuts.md +155 -0
  65. package/skills/vue-debug-guides/reference/fallthrough-attrs-overwrite-vue3.md +159 -0
  66. package/skills/vue-debug-guides/reference/in-dom-template-parsing-caveats.md +149 -0
  67. package/skills/vue-debug-guides/reference/inheritattrs-false-for-wrapper-components.md +230 -0
  68. package/skills/vue-debug-guides/reference/keepalive-router-nested-double-mount.md +222 -0
  69. package/skills/vue-debug-guides/reference/keepalive-transition-memory-leak.md +144 -0
  70. package/skills/vue-debug-guides/reference/keyup-modifier-timing.md +137 -0
  71. package/skills/vue-debug-guides/reference/lifecycle-dom-access-timing.md +216 -0
  72. package/skills/vue-debug-guides/reference/lifecycle-hooks-synchronous-registration.md +156 -0
  73. package/skills/vue-debug-guides/reference/lifecycle-ssr-awareness.md +184 -0
  74. package/skills/vue-debug-guides/reference/local-components-not-in-descendants.md +151 -0
  75. package/skills/vue-debug-guides/reference/mount-return-value.md +88 -0
  76. package/skills/vue-debug-guides/reference/multi-root-component-class-attrs.md +93 -0
  77. package/skills/vue-debug-guides/reference/native-event-collision-with-emits.md +162 -0
  78. package/skills/vue-debug-guides/reference/no-passive-with-prevent.md +141 -0
  79. package/skills/vue-debug-guides/reference/no-v-if-with-v-for.md +136 -0
  80. package/skills/vue-debug-guides/reference/perf-computed-object-stability.md +157 -0
  81. package/skills/vue-debug-guides/reference/perf-props-stability-update-optimization.md +140 -0
  82. package/skills/vue-debug-guides/reference/plugin-global-properties-sparingly.md +109 -0
  83. package/skills/vue-debug-guides/reference/plugin-install-before-mount.md +124 -0
  84. package/skills/vue-debug-guides/reference/plugin-prefer-provide-inject-over-global-properties.md +120 -0
  85. package/skills/vue-debug-guides/reference/plugin-typescript-type-augmentation.md +157 -0
  86. package/skills/vue-debug-guides/reference/prop-defineprops-scope-limitation.md +161 -0
  87. package/skills/vue-debug-guides/reference/provide-inject-debugging-challenges.md +203 -0
  88. package/skills/vue-debug-guides/reference/provide-inject-default-value-factory.md +244 -0
  89. package/skills/vue-debug-guides/reference/provide-inject-reactivity-not-automatic.md +226 -0
  90. package/skills/vue-debug-guides/reference/provide-inject-synchronous-setup.md +235 -0
  91. package/skills/vue-debug-guides/reference/reactive-destructuring.md +89 -0
  92. package/skills/vue-debug-guides/reference/reactivity-debugging-hooks.md +132 -0
  93. package/skills/vue-debug-guides/reference/reactivity-markraw-for-non-reactive.md +149 -0
  94. package/skills/vue-debug-guides/reference/reactivity-proxy-identity-hazard.md +96 -0
  95. package/skills/vue-debug-guides/reference/reactivity-same-tick-batching.md +166 -0
  96. package/skills/vue-debug-guides/reference/ref-value-access.md +61 -0
  97. package/skills/vue-debug-guides/reference/refs-in-collections-need-value.md +81 -0
  98. package/skills/vue-debug-guides/reference/render-function-avoid-internal-vnode-properties.md +151 -0
  99. package/skills/vue-debug-guides/reference/render-function-vnodes-must-be-unique.md +133 -0
  100. package/skills/vue-debug-guides/reference/rendering-render-function-h-import-vue3.md +148 -0
  101. package/skills/vue-debug-guides/reference/rendering-render-function-return-from-setup.md +148 -0
  102. package/skills/vue-debug-guides/reference/rendering-render-function-slots-as-functions.md +168 -0
  103. package/skills/vue-debug-guides/reference/rendering-resolve-component-for-string-names.md +231 -0
  104. package/skills/vue-debug-guides/reference/select-initial-value-ios-bug.md +91 -0
  105. package/skills/vue-debug-guides/reference/self-referencing-component-name.md +157 -0
  106. package/skills/vue-debug-guides/reference/sfc-named-exports-forbidden.md +184 -0
  107. package/skills/vue-debug-guides/reference/sfc-scoped-css-child-component-styling.md +156 -0
  108. package/skills/vue-debug-guides/reference/sfc-scoped-css-dynamic-content.md +193 -0
  109. package/skills/vue-debug-guides/reference/sfc-scoped-css-slot-content.md +242 -0
  110. package/skills/vue-debug-guides/reference/sfc-script-setup-reactivity.md +195 -0
  111. package/skills/vue-debug-guides/reference/slot-forwarding-to-child-components.md +143 -0
  112. package/skills/vue-debug-guides/reference/slot-implicit-default-content.md +155 -0
  113. package/skills/vue-debug-guides/reference/slot-name-reserved-prop.md +109 -0
  114. package/skills/vue-debug-guides/reference/slot-named-scoped-explicit-default.md +95 -0
  115. package/skills/vue-debug-guides/reference/slot-render-scope-parent-only.md +135 -0
  116. package/skills/vue-debug-guides/reference/slot-v-slot-on-components-or-templates-only.md +122 -0
  117. package/skills/vue-debug-guides/reference/ssr-hydration-mismatch-causes.md +280 -0
  118. package/skills/vue-debug-guides/reference/ssr-platform-specific-apis.md +256 -0
  119. package/skills/vue-debug-guides/reference/state-ssr-cross-request-pollution.md +276 -0
  120. package/skills/vue-debug-guides/reference/suspense-no-builtin-error-handling.md +127 -0
  121. package/skills/vue-debug-guides/reference/suspense-ssr-hydration-issues.md +159 -0
  122. package/skills/vue-debug-guides/reference/tailwind-dynamic-class-generation.md +144 -0
  123. package/skills/vue-debug-guides/reference/teleport-scoped-styles-limitation.md +191 -0
  124. package/skills/vue-debug-guides/reference/teleport-ssr-hydration.md +152 -0
  125. package/skills/vue-debug-guides/reference/teleport-target-must-exist.md +113 -0
  126. package/skills/vue-debug-guides/reference/template-expressions-restrictions.md +114 -0
  127. package/skills/vue-debug-guides/reference/template-functions-no-side-effects.md +187 -0
  128. package/skills/vue-debug-guides/reference/template-ref-null-with-v-if.md +123 -0
  129. package/skills/vue-debug-guides/reference/template-ref-unwrapping-top-level.md +104 -0
  130. package/skills/vue-debug-guides/reference/template-ref-v-for-order.md +172 -0
  131. package/skills/vue-debug-guides/reference/textarea-no-interpolation.md +72 -0
  132. package/skills/vue-debug-guides/reference/transition-group-flip-inline-elements.md +152 -0
  133. package/skills/vue-debug-guides/reference/transition-group-move-animation-position-absolute.md +130 -0
  134. package/skills/vue-debug-guides/reference/transition-group-no-default-wrapper-vue3.md +152 -0
  135. package/skills/vue-debug-guides/reference/transition-js-hooks-done-callback.md +251 -0
  136. package/skills/vue-debug-guides/reference/transition-nested-duration.md +182 -0
  137. package/skills/vue-debug-guides/reference/transition-reusable-scoped-style.md +245 -0
  138. package/skills/vue-debug-guides/reference/transition-router-view-appear.md +193 -0
  139. package/skills/vue-debug-guides/reference/transition-type-when-mixed.md +172 -0
  140. package/skills/vue-debug-guides/reference/transition-unmount-hook-timing.md +149 -0
  141. package/skills/vue-debug-guides/reference/ts-defineprops-boolean-default-false.md +225 -0
  142. package/skills/vue-debug-guides/reference/ts-defineprops-imported-types-limitations.md +281 -0
  143. package/skills/vue-debug-guides/reference/ts-event-handler-explicit-typing.md +213 -0
  144. package/skills/vue-debug-guides/reference/ts-reactive-no-generic-argument.md +196 -0
  145. package/skills/vue-debug-guides/reference/ts-shallowref-for-dynamic-components.md +218 -0
  146. package/skills/vue-debug-guides/reference/ts-template-ref-null-handling.md +249 -0
  147. package/skills/vue-debug-guides/reference/ts-template-type-casting.md +214 -0
  148. package/skills/vue-debug-guides/reference/ts-withdefaults-mutable-factory-function.md +171 -0
  149. package/skills/vue-debug-guides/reference/undeclared-emits-double-firing.md +195 -0
  150. package/skills/vue-debug-guides/reference/use-template-ref-vue35.md +158 -0
  151. package/skills/vue-debug-guides/reference/v-else-must-follow-v-if.md +136 -0
  152. package/skills/vue-debug-guides/reference/v-for-component-props.md +95 -0
  153. package/skills/vue-debug-guides/reference/v-for-computed-reverse-sort.md +86 -0
  154. package/skills/vue-debug-guides/reference/v-for-key-attribute.md +90 -0
  155. package/skills/vue-debug-guides/reference/v-for-range-starts-at-one.md +66 -0
  156. package/skills/vue-debug-guides/reference/v-if-null-check-order.md +171 -0
  157. package/skills/vue-debug-guides/reference/v-model-ignores-html-attributes.md +83 -0
  158. package/skills/vue-debug-guides/reference/v-model-ime-composition.md +83 -0
  159. package/skills/vue-debug-guides/reference/v-model-number-modifier-behavior.md +124 -0
  160. package/skills/vue-debug-guides/reference/v-show-template-limitation.md +124 -0
  161. package/skills/vue-debug-guides/reference/watch-async-cleanup.md +180 -0
  162. package/skills/vue-debug-guides/reference/watch-async-creation-memory-leak.md +176 -0
  163. package/skills/vue-debug-guides/reference/watch-deep-same-object-reference.md +165 -0
  164. package/skills/vue-debug-guides/reference/watch-flush-timing.md +189 -0
  165. package/skills/vue-debug-guides/reference/watch-reactive-property-getter.md +108 -0
  166. package/skills/vue-debug-guides/reference/watcheffect-async-dependency-tracking.md +173 -0
  167. package/skills/vue-debug-guides/reference/watcheffect-flush-post-for-refs.md +176 -0
  168. package/skills/vue-jsx-best-practices/SKILL.md +12 -0
  169. package/skills/vue-jsx-best-practices/reference/render-function-jsx-vue-vs-react.md +141 -0
  170. package/skills/vue-options-api-best-practices/SKILL.md +23 -0
  171. package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-lifecycle-hooks.md +95 -0
  172. package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-methods.md +68 -0
  173. package/skills/vue-options-api-best-practices/reference/stateful-methods-lifecycle.md +61 -0
  174. package/skills/vue-options-api-best-practices/reference/ts-options-api-arrow-functions-validators.md +141 -0
  175. package/skills/vue-options-api-best-practices/reference/ts-options-api-computed-return-types.md +192 -0
  176. package/skills/vue-options-api-best-practices/reference/ts-options-api-proptype-complex-types.md +212 -0
  177. package/skills/vue-options-api-best-practices/reference/ts-options-api-provide-inject-limitations.md +135 -0
  178. package/skills/vue-options-api-best-practices/reference/ts-options-api-type-event-handlers.md +202 -0
  179. package/skills/vue-options-api-best-practices/reference/ts-options-api-use-definecomponent.md +172 -0
  180. package/skills/vue-options-api-best-practices/reference/ts-strict-mode-options-api.md +197 -0
  181. package/skills/vue-pinia-best-practices/SKILL.md +21 -0
  182. package/skills/vue-pinia-best-practices/reference/pinia-no-active-pinia-error.md +248 -0
  183. package/skills/vue-pinia-best-practices/reference/pinia-setup-store-return-all-state.md +227 -0
  184. package/skills/vue-pinia-best-practices/reference/pinia-store-destructuring-breaks-reactivity.md +193 -0
  185. package/skills/vue-pinia-best-practices/reference/state-url-for-ephemeral-filters.md +238 -0
  186. package/skills/vue-pinia-best-practices/reference/state-use-pinia-for-large-apps.md +262 -0
  187. package/skills/vue-pinia-best-practices/reference/store-method-binding-parentheses.md +191 -0
  188. package/skills/vue-router-best-practices/SKILL.md +23 -0
  189. package/skills/vue-router-best-practices/reference/router-beforeenter-no-param-trigger.md +167 -0
  190. package/skills/vue-router-best-practices/reference/router-beforerouteenter-no-this.md +176 -0
  191. package/skills/vue-router-best-practices/reference/router-guard-async-await-pattern.md +227 -0
  192. package/skills/vue-router-best-practices/reference/router-navigation-guard-infinite-loop.md +187 -0
  193. package/skills/vue-router-best-practices/reference/router-navigation-guard-next-deprecated.md +150 -0
  194. package/skills/vue-router-best-practices/reference/router-param-change-no-lifecycle.md +181 -0
  195. package/skills/vue-router-best-practices/reference/router-simple-routing-cleanup.md +209 -0
  196. package/skills/vue-router-best-practices/reference/router-use-vue-router-for-production.md +183 -0
  197. package/skills/vue-testing-best-practices/SKILL.md +29 -0
  198. package/skills/vue-testing-best-practices/reference/async-component-testing.md +163 -0
  199. package/skills/vue-testing-best-practices/reference/teleport-testing-complexity.md +158 -0
  200. package/skills/vue-testing-best-practices/reference/testing-async-await-flushpromises.md +175 -0
  201. package/skills/vue-testing-best-practices/reference/testing-browser-vs-node-runners.md +208 -0
  202. package/skills/vue-testing-best-practices/reference/testing-component-blackbox-approach.md +144 -0
  203. package/skills/vue-testing-best-practices/reference/testing-composables-helper-wrapper.md +238 -0
  204. package/skills/vue-testing-best-practices/reference/testing-e2e-playwright-recommended.md +242 -0
  205. package/skills/vue-testing-best-practices/reference/testing-no-snapshot-only.md +197 -0
  206. package/skills/vue-testing-best-practices/reference/testing-pinia-store-setup.md +228 -0
  207. package/skills/vue-testing-best-practices/reference/testing-suspense-async-components.md +229 -0
  208. package/skills/vue-testing-best-practices/reference/testing-vitest-recommended-for-vue.md +204 -0
@@ -0,0 +1,184 @@
1
+ ---
2
+ title: Mounted and Unmounted Hooks Do Not Run During SSR
3
+ impact: MEDIUM
4
+ impactDescription: SSR applications may fail if mounted-only code is essential for functionality
5
+ type: capability
6
+ tags: [vue3, lifecycle, ssr, server-side-rendering, nuxt, onMounted, mounted, hydration]
7
+ ---
8
+
9
+ # Mounted and Unmounted Hooks Do Not Run During SSR
10
+
11
+ **Impact: MEDIUM** - During server-side rendering (SSR), lifecycle hooks like `mounted`, `onMounted`, `unmounted`, and `onUnmounted` are never called on the server. This can cause differences between server-rendered and client-rendered content, hydration mismatches, and missing functionality if critical logic is placed only in these hooks.
12
+
13
+ On the server, only `beforeCreate`, `created`, and their Composition API equivalents run. Client-specific operations (DOM access, browser APIs, third-party libraries) must be in mounted hooks, but you must handle the SSR case appropriately.
14
+
15
+ ## Task Checklist
16
+
17
+ - [ ] Place browser-specific code (window, document, localStorage) in mounted/onMounted
18
+ - [ ] Ensure critical data fetching happens in hooks that run on server (created)
19
+ - [ ] Handle hydration mismatches for content that differs client vs server
20
+ - [ ] Use `<ClientOnly>` wrapper (Nuxt) or conditional rendering for client-only components
21
+ - [ ] Check for browser environment before using browser APIs
22
+
23
+ **Incorrect:**
24
+ ```javascript
25
+ // WRONG: Accessing browser APIs in created - breaks SSR
26
+ export default {
27
+ created() {
28
+ // These don't exist on the server!
29
+ this.width = window.innerWidth // ReferenceError: window is not defined
30
+ this.savedData = localStorage.getItem('data') // ReferenceError: localStorage is not defined
31
+ }
32
+ }
33
+ ```
34
+
35
+ ```javascript
36
+ // WRONG: Critical initialization only in mounted - won't run on server
37
+ export default {
38
+ data() {
39
+ return { user: null }
40
+ },
41
+ async mounted() {
42
+ // This won't run on server - page renders without user data
43
+ // Then hydrates with user data - causes flash of content
44
+ this.user = await fetchCurrentUser()
45
+ }
46
+ }
47
+ ```
48
+
49
+ **Correct:**
50
+ ```javascript
51
+ // CORRECT: Data fetching in created (runs on server), DOM in mounted
52
+ export default {
53
+ data() {
54
+ return {
55
+ user: null,
56
+ windowWidth: 0
57
+ }
58
+ },
59
+ async created() {
60
+ // This runs on both server and client
61
+ this.user = await fetchCurrentUser()
62
+ },
63
+ mounted() {
64
+ // Browser-specific code safely in mounted
65
+ this.windowWidth = window.innerWidth
66
+ window.addEventListener('resize', this.handleResize)
67
+ },
68
+ unmounted() {
69
+ window.removeEventListener('resize', this.handleResize)
70
+ }
71
+ }
72
+ ```
73
+
74
+ ```vue
75
+ <!-- CORRECT: Composition API with SSR awareness -->
76
+ <script setup>
77
+ import { ref, onMounted, onUnmounted } from 'vue'
78
+
79
+ const user = ref(null)
80
+ const windowWidth = ref(0)
81
+
82
+ // This runs on both server and client (during setup)
83
+ user.value = await useFetch('/api/user')
84
+
85
+ // These only run on client
86
+ onMounted(() => {
87
+ windowWidth.value = window.innerWidth
88
+ window.addEventListener('resize', handleResize)
89
+ })
90
+
91
+ onUnmounted(() => {
92
+ window.removeEventListener('resize', handleResize)
93
+ })
94
+
95
+ function handleResize() {
96
+ windowWidth.value = window.innerWidth
97
+ }
98
+ </script>
99
+ ```
100
+
101
+ ## Checking for Browser Environment
102
+
103
+ ```javascript
104
+ // CORRECT: Guard browser API access
105
+ export default {
106
+ data() {
107
+ return { theme: 'light' }
108
+ },
109
+ created() {
110
+ // Check if we're in browser before accessing browser APIs
111
+ if (typeof window !== 'undefined') {
112
+ this.theme = localStorage.getItem('theme') || 'light'
113
+ }
114
+ },
115
+ mounted() {
116
+ // mounted only runs in browser, so this is always safe
117
+ this.applyTheme()
118
+ }
119
+ }
120
+ ```
121
+
122
+ ## Nuxt.js Specific Patterns
123
+
124
+ ```vue
125
+ <!-- CORRECT: Using Nuxt's ClientOnly for client-specific components -->
126
+ <template>
127
+ <div>
128
+ <!-- This content renders on both server and client -->
129
+ <h1>Dashboard</h1>
130
+
131
+ <!-- This only renders on client - no hydration mismatch -->
132
+ <ClientOnly>
133
+ <ChartComponent :data="chartData" />
134
+ <template #fallback>
135
+ <p>Loading chart...</p>
136
+ </template>
137
+ </ClientOnly>
138
+ </div>
139
+ </template>
140
+ ```
141
+
142
+ ```javascript
143
+ // CORRECT: Using Nuxt's process.client/process.server
144
+ export default {
145
+ created() {
146
+ if (process.client) {
147
+ // Only runs in browser
148
+ this.initAnalytics()
149
+ }
150
+ if (process.server) {
151
+ // Only runs on server
152
+ this.logServerRequest()
153
+ }
154
+ }
155
+ }
156
+ ```
157
+
158
+ ## Handling Hydration Mismatches
159
+
160
+ ```vue
161
+ <script setup>
162
+ import { ref, onMounted } from 'vue'
163
+
164
+ // Start with a value that matches what server renders
165
+ const currentTime = ref(null)
166
+
167
+ onMounted(() => {
168
+ // Update to real value only on client
169
+ // This prevents hydration mismatch
170
+ currentTime.value = new Date().toLocaleTimeString()
171
+ })
172
+ </script>
173
+
174
+ <template>
175
+ <!-- Renders null on server, then updates on client -->
176
+ <span v-if="currentTime">{{ currentTime }}</span>
177
+ <span v-else>Loading...</span>
178
+ </template>
179
+ ```
180
+
181
+ ## Reference
182
+ - [Vue.js SSR Guide](https://vuejs.org/guide/scaling-up/ssr.html)
183
+ - [Nuxt.js Lifecycle](https://nuxt.com/docs/api/composables/use-nuxt-app#lifecycle-hooks)
184
+ - [Vue SSR Hydration](https://vuejs.org/guide/scaling-up/ssr.html#client-hydration)
@@ -0,0 +1,151 @@
1
+ ---
2
+ title: Locally Registered Components Are Not Available in Descendants
3
+ impact: HIGH
4
+ impactDescription: Common source of "component not found" errors in nested components
5
+ type: gotcha
6
+ tags: [vue3, component-registration, local-registration, scope, nested-components]
7
+ ---
8
+
9
+ # Locally Registered Components Are Not Available in Descendants
10
+
11
+ **Impact: HIGH** - Locally registered components are only available in the component where they are registered, NOT in its child or descendant components. This is a common source of "Unknown component" or "Failed to resolve component" errors when developers expect a component registered in a parent to be available in children.
12
+
13
+ ## Task Checklist
14
+
15
+ - [ ] Import and register components in every file where they are used
16
+ - [ ] Do not expect parent's local components to be available in children
17
+ - [ ] If a component is needed in many places, consider global registration only as a last resort
18
+ - [ ] Use IDE auto-import features to simplify repeated imports
19
+
20
+ **Incorrect:**
21
+ ```vue
22
+ <!-- ParentComponent.vue -->
23
+ <script setup>
24
+ import Card from './Card.vue'
25
+ import ChildComponent from './ChildComponent.vue'
26
+ </script>
27
+
28
+ <template>
29
+ <Card>Parent content</Card>
30
+ <ChildComponent />
31
+ </template>
32
+ ```
33
+
34
+ ```vue
35
+ <!-- ChildComponent.vue -->
36
+ <script setup>
37
+ // WRONG: Expecting Card to be available because parent imported it
38
+ // This will cause "Failed to resolve component: Card" error
39
+ </script>
40
+
41
+ <template>
42
+ <!-- ERROR: Card is not available here! -->
43
+ <Card>
44
+ Child content
45
+ </Card>
46
+ </template>
47
+ ```
48
+
49
+ **Correct:**
50
+ ```vue
51
+ <!-- ParentComponent.vue -->
52
+ <script setup>
53
+ import Card from './Card.vue'
54
+ import ChildComponent from './ChildComponent.vue'
55
+ </script>
56
+
57
+ <template>
58
+ <Card>Parent content</Card>
59
+ <ChildComponent />
60
+ </template>
61
+ ```
62
+
63
+ ```vue
64
+ <!-- ChildComponent.vue -->
65
+ <script setup>
66
+ // CORRECT: Each component must import what it uses
67
+ import Card from './Card.vue'
68
+ </script>
69
+
70
+ <template>
71
+ <Card>
72
+ Child content
73
+ </Card>
74
+ </template>
75
+ ```
76
+
77
+ ## Common Scenarios
78
+
79
+ ### Scenario 1: Deeply Nested Components
80
+ ```vue
81
+ <!-- GrandchildComponent.vue -->
82
+ <script setup>
83
+ // Even if parent and grandparent both use Card,
84
+ // grandchild must import it separately
85
+ import Card from '@/components/Card.vue'
86
+ import Button from '@/components/Button.vue'
87
+ </script>
88
+
89
+ <template>
90
+ <Card>
91
+ <Button>Click me</Button>
92
+ </Card>
93
+ </template>
94
+ ```
95
+
96
+ ### Scenario 2: Slot Content with Components
97
+ ```vue
98
+ <!-- Parent.vue -->
99
+ <script setup>
100
+ import Modal from './Modal.vue'
101
+ import Form from './Form.vue'
102
+ </script>
103
+
104
+ <template>
105
+ <!-- Form is registered in Parent, so it works in slot content -->
106
+ <Modal>
107
+ <Form /> <!-- This works because slot content is compiled in Parent's scope -->
108
+ </Modal>
109
+ </template>
110
+ ```
111
+
112
+ ```vue
113
+ <!-- Modal.vue -->
114
+ <script setup>
115
+ // Modal doesn't need to import Form because slot content
116
+ // is compiled in the parent's scope, not Modal's scope
117
+ </script>
118
+
119
+ <template>
120
+ <div class="modal">
121
+ <slot /> <!-- Form component works here because it's parent's slot content -->
122
+ </div>
123
+ </template>
124
+ ```
125
+
126
+ ### Scenario 3: Dynamic Components
127
+ ```vue
128
+ <!-- Container.vue -->
129
+ <script setup>
130
+ import TabA from './TabA.vue'
131
+ import TabB from './TabB.vue'
132
+ import { ref, shallowRef } from 'vue'
133
+
134
+ // When using dynamic components, all possible components must be imported
135
+ const currentTab = shallowRef(TabA)
136
+ </script>
137
+
138
+ <template>
139
+ <component :is="currentTab" />
140
+ </template>
141
+ ```
142
+
143
+ ## Why This Design?
144
+
145
+ Local registration provides:
146
+ 1. **Explicit dependencies** - You can see exactly what each component uses
147
+ 2. **Tree-shaking** - Unused components are removed from bundles
148
+ 3. **Clear scope** - No magic or implicit behavior
149
+
150
+ ## Reference
151
+ - [Vue.js Component Registration - Local Registration](https://vuejs.org/guide/components/registration.html#local-registration)
@@ -0,0 +1,88 @@
1
+ ---
2
+ title: mount() Returns Component Instance, Not App Instance
3
+ impact: MEDIUM
4
+ impactDescription: Using mount() return value for app configuration silently fails
5
+ type: capability
6
+ tags: [vue3, createApp, mount, api]
7
+ ---
8
+
9
+ # mount() Returns Component Instance, Not App Instance
10
+
11
+ **Impact: MEDIUM** - The `.mount()` method returns the root component instance, not the application instance. Attempting to chain app configuration methods after mount() will fail or produce unexpected behavior.
12
+
13
+ This is a subtle API detail that catches developers who assume mount() returns the app for continued chaining.
14
+
15
+ ## Task Checklist
16
+
17
+ - [ ] Never chain app configuration methods after mount()
18
+ - [ ] If you need both instances, store them separately
19
+ - [ ] Use the component instance for accessing root component state or methods
20
+ - [ ] Use the app instance for configuration, plugins, and global registration
21
+
22
+ **Incorrect:**
23
+ ```javascript
24
+ import { createApp } from 'vue'
25
+ import App from './App.vue'
26
+
27
+ // WRONG: Assuming mount returns app instance
28
+ const app = createApp(App).mount('#app')
29
+
30
+ // This fails! app is actually the root component instance
31
+ app.use(router) // TypeError: app.use is not a function
32
+ app.config.errorHandler = fn // app.config is undefined
33
+ ```
34
+
35
+ ```javascript
36
+ // WRONG: Trying to save both in one line
37
+ const { app, component } = createApp(App).mount('#app') // Doesn't work this way
38
+ ```
39
+
40
+ **Correct:**
41
+ ```javascript
42
+ import { createApp } from 'vue'
43
+ import App from './App.vue'
44
+
45
+ // Store app instance separately
46
+ const app = createApp(App)
47
+
48
+ // Configure the app
49
+ app.use(router)
50
+ app.config.errorHandler = (err) => console.error(err)
51
+
52
+ // Store component instance if needed
53
+ const rootComponent = app.mount('#app')
54
+
55
+ // Now you have access to both:
56
+ // - app: the application instance (for config, plugins)
57
+ // - rootComponent: the root component instance (for state, methods)
58
+ ```
59
+
60
+ ```javascript
61
+ // If you only need the app configured and mounted (most common case):
62
+ createApp(App)
63
+ .use(router)
64
+ .use(pinia)
65
+ .mount('#app') // Return value (component instance) discarded - that's fine
66
+ ```
67
+
68
+ ## When You Need the Root Component Instance
69
+
70
+ ```javascript
71
+ const app = createApp(App)
72
+ const vm = app.mount('#app')
73
+
74
+ // Access root component's exposed state/methods
75
+ console.log(vm.someExposedProperty)
76
+ vm.someExposedMethod()
77
+
78
+ // In Vue 3 with <script setup>, use defineExpose to expose:
79
+ // <script setup>
80
+ // import { ref } from 'vue'
81
+ // const count = ref(0)
82
+ // defineExpose({ count })
83
+ // </script>
84
+ ```
85
+
86
+ ## Reference
87
+ - [Vue.js - Mounting the App](https://vuejs.org/guide/essentials/application.html#mounting-the-app)
88
+ - [Vue.js Application API - mount()](https://vuejs.org/api/application.html#app-mount)
@@ -0,0 +1,93 @@
1
+ # Multi-Root Component Class Attribute Inheritance
2
+
3
+ ## Rule
4
+
5
+ When a Vue 3 component has multiple root elements, class and style bindings from the parent will NOT automatically fall through. You must explicitly bind `$attrs.class` or `$attrs.style` to the target element.
6
+
7
+ ## Why This Matters
8
+
9
+ - Vue 3 components can have multiple root elements (fragments)
10
+ - Unlike single-root components, multi-root components have no automatic attribute fallthrough
11
+ - Without explicit handling, classes and styles passed from parent are silently ignored
12
+ - Vue will emit a runtime warning, but styles/classes simply won't apply
13
+
14
+ ## Bad Code
15
+
16
+ ```vue
17
+ <!-- ChildComponent.vue - WRONG: classes from parent won't apply -->
18
+ <template>
19
+ <header>Header</header>
20
+ <main>Content</main>
21
+ <footer>Footer</footer>
22
+ </template>
23
+
24
+ <!-- Parent usage -->
25
+ <ChildComponent class="my-custom-class" />
26
+ <!-- Result: my-custom-class is NOT applied to any element -->
27
+ ```
28
+
29
+ ## Good Code
30
+
31
+ ```vue
32
+ <!-- ChildComponent.vue - CORRECT: explicitly bind $attrs.class -->
33
+ <template>
34
+ <header>Header</header>
35
+ <main :class="$attrs.class" :style="$attrs.style">Content</main>
36
+ <footer>Footer</footer>
37
+ </template>
38
+
39
+ <!-- Or bind all attrs to one element -->
40
+ <template>
41
+ <header>Header</header>
42
+ <main v-bind="$attrs">Content</main>
43
+ <footer>Footer</footer>
44
+ </template>
45
+ ```
46
+
47
+ ## Accessing $attrs in script setup
48
+
49
+ ```vue
50
+ <script setup>
51
+ import { useAttrs } from 'vue'
52
+ const attrs = useAttrs()
53
+ // attrs.class and attrs.style are available
54
+ </script>
55
+
56
+ <template>
57
+ <header>Header</header>
58
+ <main :class="attrs.class">Content</main>
59
+ <footer>Footer</footer>
60
+ </template>
61
+ ```
62
+
63
+ ## Disabling Automatic Inheritance
64
+
65
+ For single-root components where you want to control attribute placement:
66
+
67
+ ```vue
68
+ <script>
69
+ export default {
70
+ inheritAttrs: false
71
+ }
72
+ </script>
73
+
74
+ <script setup>
75
+ import { useAttrs } from 'vue'
76
+ const attrs = useAttrs()
77
+ </script>
78
+
79
+ <template>
80
+ <div class="wrapper">
81
+ <input v-bind="attrs" />
82
+ </div>
83
+ </template>
84
+ ```
85
+
86
+ ## Vue 2 to Vue 3 Migration Note
87
+
88
+ In Vue 2, `$attrs` did NOT include `class` and `style`. In Vue 3, `$attrs` contains ALL attributes including `class` and `style`. This is a breaking change that affects how you handle attribute forwarding.
89
+
90
+ ## References
91
+
92
+ - [Fallthrough Attributes](https://vuejs.org/guide/components/attrs.html)
93
+ - [Vue 3 Migration Guide - $attrs includes class & style](https://v3-migration.vuejs.org/breaking-changes/attrs-includes-class-style)
@@ -0,0 +1,162 @@
1
+ ---
2
+ title: Declaring Native Event Names in Emits Blocks Native Listeners
3
+ impact: MEDIUM
4
+ impactDescription: Declaring native events like 'click' in emits prevents native DOM event listeners from working
5
+ type: gotcha
6
+ tags: [vue3, emits, native-events, click, event-collision]
7
+ ---
8
+
9
+ # Declaring Native Event Names in Emits Blocks Native Listeners
10
+
11
+ **Impact: MEDIUM** - When you declare a native DOM event name (like `click`, `input`, `focus`) in your component's `emits` option, listeners for that event will ONLY respond to your component's `emit()` calls. They will no longer respond to the actual native DOM events on the root element.
12
+
13
+ This can cause unexpected behavior where clicks seem to stop working on your component.
14
+
15
+ ## Task Checklist
16
+
17
+ - [ ] Understand that declaring native event names changes listener behavior
18
+ - [ ] Always emit the event when you declare it
19
+ - [ ] Don't declare native events if you want fallthrough behavior
20
+ - [ ] Test click/input handling after adding emits declarations
21
+
22
+ ## The Problem
23
+
24
+ **Incorrect - Declaring but not emitting:**
25
+ ```vue
26
+ <!-- ClickableCard.vue -->
27
+ <script setup>
28
+ // Declared 'click' but never emit it!
29
+ const emit = defineEmits(['click', 'select'])
30
+ </script>
31
+
32
+ <template>
33
+ <div class="card">
34
+ <slot></slot>
35
+ </div>
36
+ </template>
37
+ ```
38
+
39
+ ```vue
40
+ <!-- Parent.vue -->
41
+ <template>
42
+ <!-- This NEVER fires! Native clicks are blocked -->
43
+ <ClickableCard @click="handleClick">
44
+ Click me
45
+ </ClickableCard>
46
+ </template>
47
+ ```
48
+
49
+ **Why it fails:**
50
+ 1. `click` is declared in `emits`
51
+ 2. Vue treats `@click` as a component event listener
52
+ 3. Native click on the `<div>` doesn't trigger component event
53
+ 4. Since `emit('click')` is never called, handler never fires
54
+
55
+ ## The Solution
56
+
57
+ **Option 1: Emit the event explicitly:**
58
+ ```vue
59
+ <!-- ClickableCard.vue -->
60
+ <script setup>
61
+ const emit = defineEmits(['click', 'select'])
62
+ </script>
63
+
64
+ <template>
65
+ <!-- Explicitly emit click when div is clicked -->
66
+ <div class="card" @click="emit('click', $event)">
67
+ <slot></slot>
68
+ </div>
69
+ </template>
70
+ ```
71
+
72
+ **Option 2: Don't declare native events (use fallthrough):**
73
+ ```vue
74
+ <!-- ClickableCard.vue -->
75
+ <script setup>
76
+ // Only declare custom events, not native ones
77
+ const emit = defineEmits(['select', 'custom-action'])
78
+ </script>
79
+
80
+ <template>
81
+ <!-- Native @click from parent falls through to this div -->
82
+ <div class="card">
83
+ <slot></slot>
84
+ </div>
85
+ </template>
86
+ ```
87
+
88
+ ```vue
89
+ <!-- Parent.vue -->
90
+ <template>
91
+ <!-- Native click falls through and works -->
92
+ <ClickableCard @click="handleClick">
93
+ Click me
94
+ </ClickableCard>
95
+ </template>
96
+ ```
97
+
98
+ ## Native Events Affected
99
+
100
+ This applies to any native DOM event you might declare:
101
+
102
+ | Event | Behavior When Declared |
103
+ |-------|----------------------|
104
+ | `click` | Only responds to `emit('click')`, not native clicks |
105
+ | `input` | Only responds to `emit('input')`, not native input |
106
+ | `change` | Only responds to `emit('change')`, not native change |
107
+ | `focus` | Only responds to `emit('focus')`, not native focus |
108
+ | `blur` | Only responds to `emit('blur')`, not native blur |
109
+ | `submit` | Only responds to `emit('submit')`, not native form submit |
110
+ | `keydown` | Only responds to `emit('keydown')`, not native keydown |
111
+
112
+ ## When This Is Intentional
113
+
114
+ Sometimes you WANT to intercept native events:
115
+
116
+ ```vue
117
+ <!-- CustomInput.vue -->
118
+ <script setup>
119
+ // Intentionally intercept 'input' to transform the value
120
+ const emit = defineEmits(['input', 'update:modelValue'])
121
+
122
+ function handleInput(event) {
123
+ const transformedValue = event.target.value.toUpperCase()
124
+ emit('input', transformedValue) // Emit transformed value, not raw event
125
+ emit('update:modelValue', transformedValue)
126
+ }
127
+ </script>
128
+
129
+ <template>
130
+ <input @input="handleInput" />
131
+ </template>
132
+ ```
133
+
134
+ Here, declaring `input` is correct because you want to intercept and transform the native event before passing it to the parent.
135
+
136
+ ## Debugging Tips
137
+
138
+ If your click handlers aren't firing:
139
+
140
+ 1. Check if the event is declared in `emits`
141
+ 2. If declared, ensure you're calling `emit('click')` somewhere
142
+ 3. If you want native behavior, remove from `emits` declaration
143
+ 4. Use Vue DevTools to see which events are being emitted
144
+
145
+ ```vue
146
+ <script setup>
147
+ const emit = defineEmits(['click'])
148
+
149
+ function handleClick(event) {
150
+ console.log('Native click received, now emitting component event')
151
+ emit('click', event)
152
+ }
153
+ </script>
154
+
155
+ <template>
156
+ <div @click="handleClick">Click me</div>
157
+ </template>
158
+ ```
159
+
160
+ ## Reference
161
+ - [Vue.js Component Events](https://vuejs.org/guide/components/events.html)
162
+ - [Vue.js Fallthrough Attributes](https://vuejs.org/guide/components/attrs.html)