Skip to content

Guía del Desarrollador

Bienvenido a la documentación del front-end del proyecto Verticals Subscription E-Commerce de Alebat Education. Este documento es tu punto de partida: te da contexto general, te orienta sobre cómo funciona todo a alto nivel, y te enlaza a las secciones donde cada tema se profundiza.


Una plataforma de e-commerce educativo por suscripción desplegada actualmente como Inspiria Dental. Permite a profesionales de la salud acceder a cursos, webinars, videos, libros digitales y eventos en vivo mediante suscripciones o compras individuales.

La arquitectura está diseñada como multi-vertical: una sola base de código que puede servir múltiples marcas educativas. Cada vertical tiene su propio branding, APIs, contenido y páginas — pero comparte la infraestructura, componentes, y lógica de negocio. Actualmente solo Inspiria Dental está activa, pero el sistema está preparado para escalar a más verticales sin duplicar código.

Funcionalidades principales:

  • Streaming de video adaptativo (HLS) con seguimiento de progreso
  • Sistema de suscripciones integrado con Stripe (planes anuales/mensuales)
  • Contenido multi-idioma con fallback automático (español, inglés, portugués)
  • Catálogo de productos: cursos, libros, presenciales, series de video, lives
  • Búsqueda global, filtros por categoría, y perfiles de protagonistas/expertos
  • Dashboard de usuario con historial de compras, gestión de suscripción, y perfil

FrameworkNuxt 4.2.1 + Vue 3.5.25 + TypeScript 5.9.3
Tipo de aplicaciónSPA (Single Page Application) — sin SSR, todo client-side
UITailwind CSS 3.4 + @alebat-education/ecom-components (librería propia)
EstadoPinia 3.0 — 7 stores con persistencia en localStorage
DatosStrapi 5 (headless CMS) via capa de servicios propia
PagosStripe (checkout sessions, suscripciones, webhooks)
DeployAWS S3 + CloudFront CDN — automático al merge a main
IdiomasEspañol (default), Inglés, Portugués Brasil
Package managerpnpm (obligatorio — no uses npm ni yarn)
Repositoriogithub.com/Alebat-Education/verticals-subscription-ecommerce
URL producciónhttps://inspiriadental.com

  1. Requisitos previos

    • Node.js 20+ instalado
    • pnpm instalado globalmente (npm install -g pnpm)
    • Acceso SSH configurado para la organización Alebat-Education en GitHub
    • VS Code con las extensiones listadas abajo
  2. Clonar e instalar

    Terminal window
    git clone git@github.com:Alebat-Education/verticals-subscription-ecommerce.git
    cd verticals-subscription-ecommerce
    pnpm install
  3. Variables de entorno

    El proyecto requiere un archivo .env en la raíz que contiene URLs de APIs, keys de Stripe, tokens de servicios, y configuración de analytics. No está en el repositorio por seguridad — solicítalo al responsable del proyecto.

  4. Arrancar el servidor

    Terminal window
    pnpm dev

    El servidor arranca en http://localhost:3000 (Inspiria Dental). El puerto determina qué vertical se muestra: 3000 = primera (Inspiria), 3001 = segunda, etc.


ComandoQué haceCuándo usarlo
pnpm devServidor de desarrollo con Hot Module ReplacementMientras desarrollas
pnpm buildBuild de producción (SPA)Verificar que no hay errores de build
pnpm generateGenera sitio estático en .output/public/Lo ejecuta el CI para deploy
pnpm lint:fixEjecuta ESLint y auto-corrige lo que puedaAntes de commitear, o si el hook falla
pnpm styles:fixEjecuta Stylelint en archivos CSS/VueSi tienes errores de estilo CSS
pnpm formatFormatea todo el proyecto con PrettierSi el formato está inconsistente
pnpm testEjecuta tests unitarios (Vitest)Antes de crear PR
pnpm cleanLimpia .nuxt/, .output/, node_modules/.cache/Si algo se comporta raro tras un cambio de dependencias

Estas reglas están enforced por ESLint + pre-commit hooks. Si las violas, git commit falla y no puedes avanzar. No son sugerencias — son restricciones del proyecto:

#ProhibidoQué hacer en su lugarPor qué
1varconst (default) o let si necesitas reasignarBlock scoping, evita bugs por hoisting
2console.log()Eliminar toda traza de debug antes de commitPerformance en prod, no exponer datos internos
3SVGs inline en templates<Icon name="heroicons:nombre" />Consistencia, mantenibilidad, bundle size
4import { ref } from 'vue'Usar ref() directamente (auto-importado)Nuxt auto-importa toda la API de Vue
5any en TypeScriptTipo específico, o unknown con type narrowingType safety — any desactiva todas las protecciones
6Colores hardcodeados (#00ffa8, rgb(...))Clases Tailwind: bg-primary, text-graphiteLos colores cambian por vertical, deben ser dinámicos
7this.$route / this.$routerComposables: useRoute(), useRouter()Más testeable, funciona en <script setup>
8Mutar props directamenteEmitir un evento al padre con el nuevo valorFlujo de datos unidireccional — evita bugs difíciles de rastrear
9Comentarios HTML (<!-- ... -->)Eliminar antes de commitCódigo comentado no va a producción
10Magic strings/numbersExtraer a constants/ como constante nombradaSingle source of truth, refactoring seguro

Para una lista extendida con más reglas de calidad y anti-patrones comunes, lee Buenas Prácticas y Lo que NUNCA debes hacer.


Cómo funciona el proyecto (vista de pájaro)

Section titled “Cómo funciona el proyecto (vista de pájaro)”

Entender estos 4 conceptos es suficiente para empezar a ser productivo:

1. Páginas son delegadores, layouts tienen la lógica

Section titled “1. Páginas son delegadores, layouts tienen la lógica”

Las páginas (app/pages/) son archivos de ~7 líneas. No contienen UI ni lógica. Solo invocan un layout que depende de la vertical activa:

<!-- app/pages/courses/index.vue — TODA la página es esto -->
<script setup lang="ts">
import { chooseLayoutPage } from '~/core/plugins'
const layout = chooseLayoutPage({ page: 'courses', commonLayout: false })
</script>
<template>
<NuxtLayout :name="layout"></NuxtLayout>
</template>

La UI real vive en app/layouts/pages/inspiria/courses.vue (200+ líneas). Esto permite que la misma ruta muestre contenido diferente por vertical.

Más detalles: Tutorial: Crear una Página

2. Datos del backend siempre via useServices

Section titled “2. Datos del backend siempre via useServices”

Nunca importes un servicio directamente. Siempre usa el composable useServices:

// Modo reactivo — se actualiza con navegación, incluye loading state
const { data, isPending } = useServices('getCourses')
// Con parámetros dinámicos
const { data } = useServices('getCourseBySlug', { slug: route.params.slug })
// Modo promesa — para lógica imperativa
const result = await useServices('getCourses', undefined, { promise: true })

useServices resuelve la función correcta desde la vertical activa, inyecta el idioma del usuario, y aplica un sistema de fallback que rellena campos vacíos con traducciones del idioma por defecto (español).

Más detalles: Servicios y useServices

3. Componentes compartidos vienen de ecom-components

Section titled “3. Componentes compartidos vienen de ecom-components”

La librería @alebat-education/ecom-components provee 30+ componentes prefijados con AE:

<AEMainCard :product="course" />
<AETheModal v-model="showModal">...</AETheModal>
<AETheAlert />
<AEMainButton @click="buy">Comprar</AEMainButton>

No necesitas importarlos — se auto-registran globalmente via el módulo Nuxt.

Más detalles: Librería ecom-components

4. Estilos con Tailwind + CSS variables por vertical

Section titled “4. Estilos con Tailwind + CSS variables por vertical”

Los colores del proyecto son CSS variables que cambian según la vertical activa. Están mapeados a clases Tailwind:

<div class="bg-primary text-white">Color principal de la marca</div>
<div class="text-graphite">Texto oscuro estándar</div>
<div class="border-secondary">Borde color secundario</div>

Nunca uses colores hex directos. Si la vertical cambia de marca, todos los colores se actualizan automáticamente.

Más detalles: Estilos y Tailwind


El proyecto usa Conventional Commits enforced por CommitLint. El formato es:

tipo(scope): descripción imperativa en minúsculas sin punto final

Tipos disponibles:

TipoCuándoEjemplo
featNueva funcionalidadfeat(checkout): add promo code validation
fixCorrección de bugfix(auth): resolve infinite loop on token refresh
refactorReestructuración sin cambio funcionalrefactor(services): extract common query builder
styleCambios de formato (no CSS)style(components): fix indentation in cards
testTests nuevos o modificadostest(buyflow): add unit tests for subscription logic
docsDocumentacióndocs(readme): update setup instructions
choreDependencias, config, buildchore(deps): update ecom-components to latest
ciPipeline CI/CDci(deploy): fix S3 sync command

Reglas del mensaje:

  • Todo en minúsculas (no Fix sino fix)
  • Verbo imperativo: add, fix, remove — no added, fixing
  • Sin punto final
  • Máximo ~72 caracteres en la primera línea

Más detalles: Buenas Prácticas: Commits y Git


1. git checkout main && git pull
2. git checkout -b 123-descripcion-corta
3. Desarrollar (commits frecuentes con conventional commits)
4. pnpm lint:fix && pnpm format (los hooks lo hacen solo, pero por si acaso)
5. git push origin 123-descripcion-corta
6. Crear PR en GitHub (con template lleno)
7. Esperar review de Copilot + revisión manual
8. Merge a main → deploy automático a producción

Estas extensiones son necesarias para que el entorno funcione correctamente con las herramientas del proyecto:

ExtensiónIDPara qué
ESLintdbaeumer.vscode-eslintMuestra errores de lint inline mientras escribes
Prettieresbenp.prettier-vscodeFormatea al guardar siguiendo las reglas del proyecto
Stylelintstylelint.vscode-stylelintValida CSS/PostCSS en archivos .vue
VolarVue.volarIntelliSense, type-checking, y soporte completo para Vue 3 + TypeScript
Tailwind IntelliSensebradlc.vscode-tailwindcssAutocomplete de clases Tailwind con preview

Usa estos enlaces para profundizar en cada área: