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
-
anyeverywhere -
this.somethingin<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/useAsyncDatafor 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.
Top comments (2)
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.
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.