Vue Claude Code Rules: Script Setup, Composables and SSR
Claude Code rules for Vue: Script Setup, Composables and SSR. Structure, data, errors, security, performance, and tests. Vue 3.5.45, Nov 2026.
paths:
- "**/*.vue"
- "**/*.ts"
Vue Claude Code Rules: Script Setup, Composables and SSR
Path-scoped Claude Code rule for Vue. It loads when a matching file is read. It does not replace CLAUDE.md.
Updated for Vue 3.5.45, Nov 2026
Do not upgrade dependencies or the framework version unless the task asks.
Project shape
New components use <script setup lang="ts"> when the project is on Vue 3 and TypeScript. Follow the existing single-file component layout. A composable is named useSomething and lives next to the feature that owns it.
Do not mix Options API and Composition API in a new component. An old Options component stays until you are asked to convert that file.
Reactivity
ref and reactive are the state. A computed derives a value. Do not copy a prop into a ref unless you need a local editable copy, and then say so.
Since Vue 3.5, destructuring defineProps() in <script setup> stays reactive. The compiler rewrites those bindings. Do not flag that. Destructuring a reactive() object, or a Pinia store without storeToRefs, still copies plain values and drops reactivity. On 3.4 and earlier, defineProps() destructure is also a plain copy unless the project turned the transform on.
A watcher has a cleanup. Stop a timer, an observer, and a request when the scope disposes. watchEffect is for a side effect you can rerun. It is not a place to derive state you could compute.
Props, emits, and templates
Declare props and emits with types. A prop is read-only. Emit the change and let the parent own the value. v-for uses a stable key, not the index, when the list can reorder.
The template stays declarative. A heavy expression moves into a computed. Do not mutate a prop or an external singleton from the template.
SSR and errors
On a Nuxt or other SSR app, do not touch window during setup. Guard it, or run the browser work in onMounted. A random id or a clock during setup will mismatch hydration. Suspense and KeepAlive need the keys and fallbacks the project already uses. Do not invent a second cache around them.
Show an error state in the component that failed. Do not swallow a failed request and render an empty list that looks successful.
Security, performance, and tests
v-html gets sanitized content or nothing. Do not bind a user string into HTML.
A large list uses the virtualization the project already has. Do not deep-watch a huge object by habit. A computed is cheaper than a watch that writes another ref.
Test a component with the project's Vue Test Utils or Testing Library setup. Assert the rendered text and the emitted event. Cover the lost-reactivity case when you change a store binding: the text updates when the store updates.
Mistakes to avoid
- Destructuring a reactive object and expecting it to stay live.
windowduring setup on an SSR page.- A prop mutated in the child.
- A watcher with no cleanup.
- A Vue 2 pattern pasted into a script-setup component.
What changed in this major
Vue 3.5 compiles destructured defineProps() so the bindings stay reactive.
Deprecated APIs to never generate
Vue.filter was removed in Vue 3. Use a function or a computed. new Vue() was removed. Use createApp.
Commands
Run the Vue unit test script.
Example
<script setup lang="ts">
const { label = "Save" } = defineProps<{ label?: string }>()
</script>
On Vue 3.5 that binding stays reactive.