Buenas Prácticas y Reglas
Reglas críticas (rompen el build o el commit)
Section titled “Reglas críticas (rompen el build o el commit)”Enforced por ESLint + pre-commit hooks. Si las violas, git commit falla:
| Prohibido | Usar en su lugar | Motivo |
|---|---|---|
var | const / let | Block scoping, evita hoisting |
console.log() | Eliminar | Performance y seguridad en producción |
| SVGs inline en template | <Icon name="..." /> | Consistencia, mantenibilidad |
import { ref } from 'vue' | Usar ref() directo | Auto-imports de Nuxt |
any en TypeScript | Tipo específico o unknown | Type safety |
| Colores hardcodeados | CSS variables o clases Tailwind | Theming por vertical |
$route / $router | useRoute() / useRouter() | Composable pattern, testeable |
| Mutar props | Emitir evento al padre | Flujo unidireccional |
Comentarios HTML <!-- --> | Eliminar | No code comentado en producción |
| Magic strings/numbers | Extraer a constants/ | Single source of truth |
Reglas importantes (calidad)
Section titled “Reglas importantes (calidad)”| Práctica | Detalle |
|---|---|
| Tipar props | defineProps<{ title: string }>() — siempre con interface |
| Tipar emits | defineEmits<{ close: [] }>() — siempre explícito |
| Imports no usados | Eliminar (ESLint los detecta) |
| Lógica duplicada | Extraer a composable si se repite 2+ veces |
| Error handling | Try-catch en toda llamada a API |
| Accesibilidad | ARIA attributes en elementos interactivos |
| BEM en SCSS | .block__element--modifier |
| Mobile-first | Estilos base para móvil, luego md:, lg: |
Orden dentro de <script setup>
Section titled “Orden dentro de <script setup>”Sigue este orden para consistencia entre componentes:
// 1. Interfaces/Types localesinterface Props { ... }
// 2. Props y Emitsconst props = defineProps<Props>()const emit = defineEmits<{ ... }>()
// 3. Composables y storesconst route = useRoute()const { showAlert } = useShowAlert()const authStore = useAuthStore()
// 4. Estado reactivo (refs)const isLoading = ref(false)const items = ref<Item[]>([])
// 5. Computedsconst filteredItems = computed(() => ...)
// 6. Watcherswatch(() => props.id, (newId) => { ... })
// 7. Funciones/métodosasync function fetchData() { ... }function handleClick() { ... }
// 8. Lifecycle hooksonMounted(fetchData)Convenciones de commit (Conventional Commits)
Section titled “Convenciones de commit (Conventional Commits)”Enforced por CommitLint. Formato:
tipo(scope): descripción imperativa en minúsculas| Tipo | Cuándo usar |
|---|---|
feat | Nueva funcionalidad para el usuario |
fix | Corrección de bug |
refactor | Reestructuración sin cambio funcional |
style | Cambios de formato (no CSS — eso es refactor) |
test | Tests nuevos o modificados |
docs | Documentación |
chore | Dependencias, configuración, build |
ci | Pipeline CI/CD |
Ejemplos buenos
Section titled “Ejemplos buenos”feat(checkout): add discount code validationfix(auth): resolve infinite loop on token refreshrefactor(services): extract common query builderchore(deps): update ecom-components to latesttest(buyflow): add unit tests for subscription popup logicReglas del mensaje
Section titled “Reglas del mensaje”- Todo en minúsculas (no empezar con mayúscula)
- Sin punto final
- Verbo en imperativo: “add” no “added” ni “adding”
- Máximo ~72 caracteres en primera línea
- Scope es opcional pero recomendado
Branches
Section titled “Branches”Formato: [número-issue]-[descripción-corta-en-kebab-case]
302-typing-refactorization330-implement-pdf-download343-add-discount-connectionPre-commit hooks
Section titled “Pre-commit hooks”Al ejecutar git commit, Husky lanza automáticamente:
- ESLint → auto-fix en archivos
.ts,.vue - Stylelint → auto-fix en archivos
.css,.scss,.vue - Prettier → formateo general
- CommitLint → valida formato del mensaje
Si cualquiera falla → commit abortado. Corrige el error y reintenta.
Tip: Si el hook corrige archivos automáticamente, necesitarás hacer git add . de nuevo antes de reintentar el commit.
Flujo de PR completo
Section titled “Flujo de PR completo”1. Actualiza main: git checkout main && git pull2. Crea branch: git checkout -b 999-mi-feature3. Desarrolla con commits frecuentes (conventional commits)4. Pre-commit: pnpm lint:fix && pnpm styles:fix && pnpm format5. Push: git push -u origin 999-mi-feature6. Crea PR en GitHub con template: - Issue vinculado (#999) - Tipo de cambio (feature/fix/refactor) - Descripción de lo implementado - Screenshots si hay cambios de UI7. GitHub Copilot hace auto-review8. Corrige feedback del review9. Merge a main → deploy automático a producción10. Elimina la branchPerformance
Section titled “Performance”| Práctica | Cuándo aplicar |
|---|---|
shallowRef | Objetos grandes que no necesitan reactividad profunda en propiedades internas |
v-memo | Listas largas con renders costosos que raramente cambian |
defineAsyncComponent | Componentes pesados (modales, PDFs, widgets) |
| Lazy-load de rutas | Nuxt lo hace automático por cada página |
v-if vs v-show | v-if si se muestra rara vez; v-show si alterna frecuentemente |
Errores comunes
Section titled “Errores comunes”| Error | Causa probable | Solución |
|---|---|---|
| ”Cannot read property of undefined” | Dato no cargado aún | v-if="data" guard antes de acceder |
| ESLint falla en commit | Código con issues | pnpm lint:fix manual |
| Componente AE no renderiza | No instalado | pnpm install + verificar nuxt.config |
| Estilos no aplican | Especificidad o scoped | Verificar con DevTools |
useServices retorna null | Nombre incorrecto | Verificar que existe en visibleVertical.services |
| Ruta 404 | Archivo mal ubicado | Verificar path en pages/ |
| Alert no aparece | Llamado fuera de setup | useShowAlert() debe estar en setup del componente |
| Build falla con type error | Tipo incorrecto | vue-tsc --noEmit para ver todos los errores |