DEV Community

Mustafa Vatandaş
Mustafa Vatandaş

Posted on

How to Make Claude Code & Cursor Write Perfect Vue/Nuxt Code

If you're using Claude Code, Cursor, or GitHub Copilot for Vue/Nuxt development, you've probably seen this:

  • Options API instead of Composition API
  • JavaScript instead of TypeScript
  • Vuex instead of Pinia
  • any everywhere
  • this.something in <script setup>

The fix is simple: tell the AI your project's rules.

The Setup

I created vue-claude-stack — a drop-in config that makes AI tools generate correct Vue 3 & Nuxt 3 code.

It includes:

File Tool Purpose
CLAUDE.md Claude Code Project conventions & rules
.cursorrules Cursor AI behavior rules
.github/copilot-instructions.md Copilot Code generation guidelines
skills/ Claude Code 5 generation commands

What the AI learns

Once you drop these files in your project, the AI knows:

  • Always use <script setup lang="ts">
  • Always use defineProps<T>() with TypeScript
  • Always use Pinia setup stores (defineStore('name', () => {...}))
  • Never use Options API, mixins, or any
  • Use useFetch/useAsyncData for data fetching in Nuxt
  • Use storeToRefs() when destructuring Pinia stores

Generation Skills

The repo includes 5 Claude Code skills you can invoke directly:


bash
/generate-component UserProfile --props "name, avatar" --emits "edit"
/generate-composable useSearch
/generate-store cart --actions "add, remove, clear"  
/generate-test components/UserProfile.vue
/generate-api users/[id] --methods "get, put, delete"
Each skill generates fully typed, convention-following code.

Quick Start

# Copy everything
npx degit mvtandas/vue-claude-stack ai-config
cp -r ai-config/{CLAUDE.md,.cursorrules,.github,skills} .
Or just grab what you need:


# Just CLAUDE.md
curl -o CLAUDE.md https://raw.githubusercontent.com/mvtandas/vue-claude-stack/main/CLAUDE.md

# Just Cursor rules
curl -o .cursorrules https://raw.githubusercontent.com/mvtandas/vue-claude-stack/main/.cursorrules
Before & After
Before (no config):


<script>
export default {
  data() {
    return { name: '' }
  },
  methods: {
    async fetchUser() {
      const res = await fetch('/api/user')
      this.name = res.data.name
    }
  }
}
</script>
After (with vue-claude-stack):


<script setup lang="ts">
interface User {
  name: string
}

const { data: user } = await useFetch<User>('/api/user')
</script>

<template>
  <p>{{ user?.name }}</p>
</template>
Same prompt. Completely different output.

Stack Covered
Vue 3.5+, Nuxt 3, TypeScript strict, Pinia, VueUse, Tailwind CSS, Vitest, Zod, Vue Router.

GitHub: mvtandas/vue-claude-stack

MIT licensed. Star it if you find it useful, and feel free to fork & customize for your team.



Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
arpan_singh_121 profile image
Arpan Singh

Your detailed walkthrough of getting Claude Code and Cursor to produce clean Vue/Nuxt components really demystifies the workflow. If you think it could help even more developers, consider syndicating it on ZyVOP (zyvop.com) for broader reach.

Collapse
 
arpan_singh_121 profile image
Arpan Singh

Your walkthrough of getting Claude Code and Cursor to generate spot‑on Vue/Nuxt components really demystifies the prompt engineering needed for clean output. If you ever want to reach even more developers, consider sharing or syndicating it on ZyVOP (zyvop.com) so the community can benefit.