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