Caso real: verticals-subscription-ecommerce
Esta página analiza la implementación real de las seis herramientas en verticals-subscription-ecommerce, un front-end Nuxt 4 en producción. Sirve como referencia de “cómo queda esto montado de verdad” y como plantilla para proyectos nuevos.
Ficha del proyecto
Section titled “Ficha del proyecto”| Concepto | Detalle |
|---|---|
| Framework | Nuxt 4.2.1 / Vue 3.5.25 |
| Gestor de paquetes | pnpm 10.11.0 |
| Estilos | Tailwind CSS 3 |
| Tests | Vitest 4 |
| CMS | Strapi (@nuxtjs/strapi) |
Los archivos implicados
Section titled “Los archivos implicados”Directory.husky/
Directory_/ generado por Husky
- …
- pre-commit typecheck + lint-staged
- commit-msg commitlint
- install.mjs legacy, ya no se usa
- .lintstagedrc qué comando por extensión
- .prettierrc reglas de formato
- .stylelintrc.json reglas de CSS
- eslint.config.js reglas de JS/TS/Vue (flat config)
- commitlint.config.ts 3 líneas: importa la config compartida
- package.json scripts y dependencias
Directory.vscode/
- settings.json ajustes del editor
- extensions.json extensiones recomendadas
Dependencias instaladas
Section titled “Dependencias instaladas”Todas en devDependencies, como corresponde a herramientas que no llegan al bundle de producción:
{ "devDependencies": { "@alebat/default-alebat-config": "^1.1.0", "@commitlint/cli": "20.1.0", "@commitlint/config-conventional": "20.0.0", "eslint": "9.36.0", "eslint-config-prettier": "10.1.8", "eslint-plugin-prettier": "5.5.4", "eslint-plugin-vue": "10.6.2", "@typescript-eslint/eslint-plugin": "8.45.0", "@typescript-eslint/parser": "^8.49.0", "vue-eslint-parser": "^10.2.0", "husky": "9.1.7", "lint-staged": "16.2.7", "prettier": "3.7.3", "stylelint": "16.26.1", "stylelint-config-recommended-vue": "1.6.1", "stylelint-config-standard": "39.0.1" }}Los scripts
Section titled “Los scripts”{ "scripts": { "lint": "eslint .", "lint:fix": "eslint . --fix", "styles": "stylelint \"**/*.{vue,css}\"", "styles:fix": "stylelint \"**/*.{vue,css}\" --fix", "format": "prettier --write \"**/*.{js,ts,vue,json,css,md}\"", "analyze": "nuxi typecheck", "prepare": "husky" }}| Comando | Qué hace |
|---|---|
pnpm lint | Pasa ESLint por todo el proyecto y solo reporta. |
pnpm lint:fix | Igual, pero arregla lo que puede (incluido el formato de Prettier). |
pnpm styles | Pasa Stylelint por los .vue y .css. |
pnpm styles:fix | Igual, arreglando lo posible. |
pnpm format | Prettier sobre todo el proyecto, incluidos .json y .md (que ESLint no toca). |
pnpm analyze | Comprobación de tipos con nuxi typecheck. |
prepare | Automático tras pnpm install: instala los hooks de Husky. |
El hook pre-commit, en detalle
Section titled “El hook pre-commit, en detalle”Este es el archivo más particular de la implementación: no se limita a llamar a lint-staged, sino que antes ejecuta un typecheck completo del proyecto.
#!/bin/sh
# CONFIGURACIÓN OPTIMIZADA PARA TYPECHECK SIN SIGKILLexport NODE_OPTIONS="--max-old-space-size=24576 --max-semi-space-size=2048 --expose-gc"export NUXT_TELEMETRY_DISABLED=1
# Crear archivo temporal usando mktemp o alternativa Windowsif command -v mktemp > /dev/null 2>&1; then TEMP_FILE=$(mktemp)else TEMP_FILE="/tmp/typecheck_$$.txt"fi
# TYPECHECKecho "🔍 Ejecutando typecheck optimizado..."npx nuxi typecheck 2>&1 | tee "$TEMP_FILE"
if grep -q "error" "$TEMP_FILE"; then # imprime un banner ASCII gigante con la palabra ERROR printf "Please execute the next command to see the errors in more detail: 'npx nuxi typecheck'\n\n" printf "❌ Typecheck failed! Commit aborted. ❌\n\n" rm "$TEMP_FILE" 2>/dev/null || true exit 1fi
rm "$TEMP_FILE" 2>/dev/null || true
# LINT-STAGEDecho "🔧 Ejecutando lint-staged..."npx lint-staged --concurrent false --relative
echo "✅ Pre-commit completado exitosamente"Qué hace cada bloque
Section titled “Qué hace cada bloque”-
NODE_OPTIONS— reserva hasta 24 GB de heap para Node (--max-old-space-size=24576, en megabytes). El typecheck de un Nuxt grande consume muchísima memoria y, sin este ajuste, el proceso muere conSIGKILLa mitad de camino.--expose-gchabilita el recolector de basura manual y--max-semi-space-sizeamplía el espacio de objetos jóvenes. -
NUXT_TELEMETRY_DISABLED=1— evita la llamada de telemetría de Nuxt en cada commit. -
El archivo temporal —
mktempno existe en Git Bash de Windows en todas las instalaciones, así que hay unfallbacka/tmp/typecheck_$$.txt($$es el PID, para que dos commits simultáneos no se pisen). -
npx nuxi typecheck | tee—teecumple una doble función: muestra la salida en pantalla y la guarda en el archivo, para poder inspeccionarla después. -
grep -q "error"— si la salida contiene la palabraerror, se aborta conexit 1, y Git cancela el commit. -
npx lint-staged --concurrent false --relative— solo si el typecheck ha pasado. Los dos flags están explicados en Husky y lint-staged: secuencial para que ESLint y Stylelint no escriban el mismo.vuea la vez, y rutas relativas por compatibilidad con Windows.
install.mjs: un archivo que ya no se usa legacy
Section titled “install.mjs: un archivo que ya no se usa ”if (process.env.NODE_ENV === 'production' || process.env.CI === 'true') { process.exit(0)}const husky = (await import('husky')).defaultconsole.log(husky())Este script existe para evitar que Husky se instale en producción o en CI, donde no hay commits que validar y husky puede no estar disponible. Pero el package.json tiene "prepare": "husky", no "prepare": "node .husky/install.mjs", así que el archivo no se ejecuta nunca. Es un resto de una configuración anterior; se puede borrar sin efecto alguno.
El hook commit-msg
Section titled “El hook commit-msg”npx --no -- commitlint --edit "$1"Y la configuración que valida, en tres líneas:
import { commitLintFront } from '@alebat/default-alebat-config'
export default commitLintFrontAl ser un front, usa commitLintFront: ámbito obligatorio pero libre. Ejemplos válidos en este proyecto:
✅ feat(checkout): añadido el resumen de suscripción✅ fix(stripe): corregido el redirect tras el pago✅ chore(release): release 1.1.0El detalle de las reglas está en default-alebat-config.
Configuración del editor
Section titled “Configuración del editor”El proyecto versiona su propio .vscode/, de modo que quien clone el repositorio recibe los ajustes ya hechos.
{ "recommendations": [ "Vue.volar", "sdras.vue-vscode-snippets", "usernamehw.errorlens", "dbaeumer.vscode-eslint", "xabikos.JavaScriptSnippets", "esbenp.prettier-vscode", "cipchk.cssrem", "sibiraj-s.vscode-scss-formatter", "stylelint.vscode-stylelint", "YoavBls.pretty-ts-errors" ]}VS Code ofrece instalarlas al abrir el proyecto. Las tres imprescindibles para lo que cubre esta sección son
dbaeumer.vscode-eslint, esbenp.prettier-vscode y stylelint.vscode-stylelint.
cipchk.cssrem merece mención aparte: convierte px a rem mientras escribes, que es justo lo que hace falta con la
regla unit-allowed-list de Stylelint.
{ "css.validate": false, "scss.validate": false, "less.validate": false, "tailwindCSS.experimental.classRegex": [["class:\\s*?[\"'`]([^\"'`]*).*?,", "[\"'`]([^\"'`]*).*?[\"'`]"]], "files.associations": { "*.css": "tailwindcss" }, "editor.quickSuggestions": { "strings": true }}- Los tres
validate: falsedesactivan el linter de CSS nativo de VS Code, para que no duplique los avisos de Stylelint ni marque como error la sintaxis de Tailwind (@apply,@tailwind). files.associationstrata los.csscomo archivos de Tailwind, habilitando su IntelliSense.editor.quickSuggestions.stringsactiva el autocompletado dentro de cadenas, necesario para sugerir clases de Tailwind enclass="...".
Resumen: dónde interviene cada herramienta
Section titled “Resumen: dónde interviene cada herramienta”| Momento | Qué se ejecuta | Qué revisa |
|---|---|---|
| Al guardar en el editor | Extensiones de ESLint / Stylelint (subrayado) | Errores visibles al escribir |
git commit → pre-commit | nuxi typecheck, luego lint-staged | Tipos de todo el proyecto; ESLint y Stylelint de los archivos en staging |
git commit → commit-msg | commitlint --edit | El mensaje del commit |
| A mano, cuando quieras | pnpm lint, pnpm styles, pnpm format | Todo el proyecto |
Puesta en marcha desde cero
Section titled “Puesta en marcha desde cero”-
Clonar el repositorio.
-
Crear el
.enva partir de.env.exampley ejecutarpnpm configure:pkg, que genera el.npmrcnecesario para descargar@alebat-education/ecom-componentsde GitHub Packages. -
pnpm install— instala dependencias y, mediante el scriptprepare, configura los hooks de Husky automáticamente. -
Verificar que los hooks están activos:
.husky/_ git config core.hooksPath -
Instalar las extensiones recomendadas cuando VS Code lo ofrezca.