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 (0)