Vue 3 and Nuxt rules for AI coding agents

Vue's reactivity is forgiving until it is not: destructure a reactive object and the values stop updating, keep state at module level in a Nuxt composable and every visitor's server render shares it. These rules cover Vue 3 with the Composition API and Nuxt for server rendering, and the agent first checks vue and nuxt in package.json, since Nuxt 4 moves app code under app/ by default.

They ask for <script setup> components without mixing in the Options API, ref by default, stable :key values in v-for, Pinia stores per domain, and useFetch or useAsyncData for page data so nothing fetches twice during hydration. Server routes run in Nitro, not Vue, so composables stay out of server/ code.

Folder: rules/vue-nuxt/ · vue-nuxt.mdc, CLAUDE.md, AGENTS.md

What the Vue and Nuxt rules tell your agent

First rule of each section in vue-nuxt.mdc, quoted as shipped.

Mistakes these rules are written to prevent

Source: “Pitfalls to avoid”.

Checks the agent runs before it says done

Example commands from the Vue and Nuxt file (swap in your repo's own):

Run vue-tsc --noEmit (or nuxi typecheck), the ESLint command, the unit tests, and nuxi build when you touched server routes or rendering mode. Report each result.

Before and after: Vue and Nuxt: lost reactivity and cross-request state

Prompt card 39 · Stack: Vue 3 Composition API, Nuxt 3/4 · Type: Review and refactor · Best model: a frontier reasoning model

What the card is for

Find values that stopped being reactive (destructured reactive objects or stores, props copied into plain variables), watchers on the wrong source, and module-level state that Nuxt shares across all users on the server.

Worked example from the card

Before: composables/useCart.ts and a component

const cart = reactive({ items: [] as CartItem[], coupon: null as string | null });

export function useCart() {
  const add = (item: CartItem) => cart.items.push(item);
  return { ...cart, add };
}
<script setup lang="ts">
const { items, coupon, add } = useCart()
const total = items.reduce((s, i) => s + i.priceCents * i.qty, 0)
</script>
<template><p>{{ items.length }} items, {{ total }} cents</p></template>

Expected AI output (abridged)

1. Module-level `cart` in a Nuxt composable: created once per server process, so every
   visitor's server render shares one cart. User A's items appear in user B's HTML.
2. `{ ...cart }` spreads the reactive object into plain properties. `items` is the same
   array (so push still mutates it), but `coupon` is a snapshot string that never updates.
3. `total` is computed once at setup with reduce; it never changes when items are added.
Fix: useState for SSR-safe per-request state, computed for total, return refs.

After

export function useCart() {
  const cart = useState("cart", () => ({ items: [] as CartItem[], coupon: null as string | null }));
  const items = computed(() => cart.value.items);
  const coupon = computed(() => cart.value.coupon);
  const totalCents = computed(() => cart.value.items.reduce((s, i) => s + i.priceCents * i.qty, 0));
  function add(item: CartItem) { cart.value.items.push(item); }
  return { items, coupon, totalCents, add };
}
<script setup lang="ts">
const { items, totalCents } = useCart()
</script>
<template><p>{{ items.length }} items, {{ totalCents }} cents</p></template>

Excerpt from card 39; the prompt itself is in the pack.

Using these rules in Cursor, Claude Code and AGENTS.md tools

Cursor

Put _base.mdc and vue-nuxt.mdc in .cursor/rules/. Globs: nuxt.config.*, **/*.vue, composables/**/*.ts, server/**/*.ts, stores/**/*.ts, app/**/*.ts.

Claude Code

Root CLAUDE.md, base first. Path-scoped variant .claude/rules/vue-nuxt.md for **/*.vue, server/**/*.ts, composables/**/*.ts; PostToolUse hook: npx prettier --write <file>.

AGENTS.md tools (Codex, Gemini CLI, Aider)

Base then stack in one AGENTS.md. Gemini CLI needs context.fileName; Aider needs --read AGENTS.md. Put this file in apps/web/ or the repo root. Agents use the AGENTS.md nearest to the file being edited, so a nested copy overrides a root one for that subtree.

Related stacks

← All stacks