Vue.js / Nuxt - Guía de Entorno¶
Guía para configurar el entorno de desarrollo Vue.js/Nuxt para trabajar con Claude Code.
Resumen de Capacidades¶
| Capacidad | Herramientas |
|---|---|
| Framework | Vue 3, Nuxt 3 |
| Build | Vite, Webpack |
| State | Pinia, Vuex |
| Testing | Vitest, Vue Test Utils, Cypress |
| Styling | Tailwind, UnoCSS, Vuetify |
| Type Safety | TypeScript, vue-tsc |
Instalación¶
Node.js y pnpm¶
# Windows
winget install OpenJS.NodeJS.LTS
corepack enable
corepack prepare pnpm@latest --activate
# macOS
brew install node@22
corepack enable
# Verificar
node --version # 22.x+
pnpm --version # 9.x+
Vue CLI (Opcional)¶
Crear Proyectos¶
Vue 3 + Vite (Recomendado)¶
# Crear proyecto
pnpm create vue@latest
# Opciones recomendadas:
# - TypeScript: Yes
# - JSX: No (opcional)
# - Vue Router: Yes
# - Pinia: Yes
# - Vitest: Yes
# - E2E Testing: Cypress
# - ESLint: Yes
# - Prettier: Yes
# Instalar dependencias
cd my-vue-app
pnpm install
# Desarrollo
pnpm dev
Nuxt 3 (Full-stack)¶
# Crear proyecto Nuxt
pnpm dlx nuxi@latest init my-nuxt-app
cd my-nuxt-app
pnpm install
# Desarrollo
pnpm dev
# Build
pnpm build
pnpm preview
Estructura de Proyecto¶
Vue 3 + Vite¶
my-vue-app/
├── public/
│ └── favicon.ico
├── src/
│ ├── assets/
│ ├── components/
│ │ └── HelloWorld.vue
│ ├── composables/ # Composition API hooks
│ ├── stores/ # Pinia stores
│ ├── views/ # Páginas/vistas
│ ├── router/
│ │ └── index.ts
│ ├── App.vue
│ └── main.ts
├── tests/
│ ├── unit/
│ └── e2e/
├── index.html
├── vite.config.ts
├── tsconfig.json
├── package.json
└── pnpm-lock.yaml
Nuxt 3¶
my-nuxt-app/
├── .nuxt/ # Build output
├── assets/
├── components/ # Auto-import
├── composables/ # Auto-import
├── content/ # Nuxt Content
├── layouts/
├── middleware/
├── pages/ # File-based routing
├── plugins/
├── public/
├── server/ # API routes (Nitro)
│ ├── api/
│ └── middleware/
├── stores/
├── utils/ # Auto-import
├── app.vue
├── nuxt.config.ts
├── package.json
└── tsconfig.json
Composables (Composition API)¶
// composables/useCounter.ts
import { ref, computed } from 'vue'
export function useCounter(initial = 0) {
const count = ref(initial)
const doubled = computed(() => count.value * 2)
function increment() {
count.value++
}
function decrement() {
count.value--
}
return {
count,
doubled,
increment,
decrement
}
}
<!-- Uso en componente -->
<script setup lang="ts">
import { useCounter } from '@/composables/useCounter'
const { count, doubled, increment } = useCounter(10)
</script>
<template>
<div>
<p>Count: {{ count }}</p>
<p>Doubled: {{ doubled }}</p>
<button @click="increment">+</button>
</div>
</template>
State Management (Pinia)¶
// stores/user.ts
import { defineStore } from 'pinia'
interface User {
id: string
name: string
email: string
}
export const useUserStore = defineStore('user', {
state: () => ({
user: null as User | null,
isAuthenticated: false
}),
getters: {
displayName: (state) => state.user?.name ?? 'Guest'
},
actions: {
async login(email: string, password: string) {
// API call
const response = await fetch('/api/login', {
method: 'POST',
body: JSON.stringify({ email, password })
})
const user = await response.json()
this.user = user
this.isAuthenticated = true
},
logout() {
this.user = null
this.isAuthenticated = false
}
}
})
<!-- Uso en componente -->
<script setup lang="ts">
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
</script>
<template>
<div v-if="userStore.isAuthenticated">
<p>Welcome, {{ userStore.displayName }}</p>
<button @click="userStore.logout">Logout</button>
</div>
</template>
Testing¶
Vitest (Unit Tests)¶
// tests/unit/Counter.spec.ts
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import Counter from '@/components/Counter.vue'
describe('Counter', () => {
it('renders initial count', () => {
const wrapper = mount(Counter, {
props: { initialCount: 5 }
})
expect(wrapper.text()).toContain('5')
})
it('increments on click', async () => {
const wrapper = mount(Counter)
await wrapper.find('button').trigger('click')
expect(wrapper.text()).toContain('1')
})
})
Cypress (E2E)¶
// cypress/e2e/home.cy.ts
describe('Home Page', () => {
it('displays welcome message', () => {
cy.visit('/')
cy.contains('Welcome')
})
it('navigates to about', () => {
cy.visit('/')
cy.get('[data-cy="nav-about"]').click()
cy.url().should('include', '/about')
})
})
Nuxt 3 Features¶
Server API Routes¶
// server/api/users/[id].ts
export default defineEventHandler(async (event) => {
const id = getRouterParam(event, 'id')
// Fetch from database
const user = await getUserById(id)
if (!user) {
throw createError({
statusCode: 404,
message: 'User not found'
})
}
return user
})
Data Fetching¶
<script setup lang="ts">
// useFetch - SSR-friendly
const { data: users, pending, error } = await useFetch('/api/users')
// useAsyncData - más control
const { data: posts } = await useAsyncData('posts', () =>
$fetch('https://api.example.com/posts')
)
// useLazyFetch - no bloquea navegación
const { data: comments, pending: loading } = useLazyFetch('/api/comments')
</script>
Middleware¶
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
const user = useUserStore()
if (!user.isAuthenticated && to.path !== '/login') {
return navigateTo('/login')
}
})
UI Libraries¶
Vuetify 3¶
# Instalar
pnpm add vuetify
# plugins/vuetify.ts
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
import 'vuetify/styles'
export default createVuetify({
components,
directives,
theme: {
defaultTheme: 'dark'
}
})
Tailwind CSS¶
// tailwind.config.js
export default {
content: [
'./index.html',
'./src/**/*.{vue,js,ts,jsx,tsx}'
],
theme: {
extend: {}
},
plugins: []
}
UnoCSS (Nuxt)¶
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@unocss/nuxt'],
unocss: {
preflight: true
}
})
Comandos que Claude Code Ejecutará¶
# Crear proyectos
pnpm create vue@latest
pnpm dlx nuxi init my-app
# Desarrollo
pnpm dev
pnpm build
pnpm preview
# Testing
pnpm test:unit
pnpm vitest
pnpm cypress:open
pnpm cypress:run
# Linting
pnpm lint
pnpm lint:fix
vue-tsc --noEmit
# Dependencias
pnpm add package-name
pnpm add -D dev-package
pnpm update
VS Code Extensions¶
code --install-extension Vue.volar
code --install-extension Vue.vscode-typescript-vue-plugin
code --install-extension dbaeumer.vscode-eslint
code --install-extension esbenp.prettier-vscode
code --install-extension bradlc.vscode-tailwindcss
code --install-extension antfu.unocss
Verificación del Entorno¶
#!/bin/bash
echo "=== Verificación Entorno Vue ==="
echo -e "\n--- Runtime ---"
node --version
pnpm --version
echo -e "\n--- Vue ---"
pnpm dlx vue --version 2>/dev/null || echo "Vue CLI no global"
echo -e "\n--- Nuxi ---"
pnpm dlx nuxi --version 2>/dev/null || echo "Nuxi disponible via pnpm dlx"
echo -e "\n=== Verificación Completa ==="
Recursos¶
- Vue 3 Documentation
- Nuxt 3 Documentation
- Pinia Documentation
- VueUse - Composables collection
- Vuetify 3