Skip to content

Sistema Multi-Vertical

El proyecto está diseñado para servir múltiples verticales (marcas educativas) desde una sola base de código. Actualmente solo hay una vertical activa (Inspiria Dental), pero la arquitectura soporta agregar más sin duplicar código.


Una “vertical” es una instancia completa de la plataforma con:

  • Su propia marca (colores, logo, favicon)
  • Su propia API backend (Strapi diferente)
  • Sus propias páginas activas
  • Sus propios servicios de datos
  • Sus propias traducciones

Todo esto se define en un solo objeto de configuración.


app/interfaces/verticals.d.ts
export interface Verticals {
name: string // Nombre interno
subdomain: string // 'inspiriadental' → inspiriadental.com
productionApi: string // URL API producción
developmentApi: string // URL API desarrollo (http://localhost:PORT)
productionURL: string // URL del sitio en producción
primaryColor: string // Color primario (hex)
secondaryColor: string // Color secundario (hex)
favicon: string // Ruta al favicon
verticalLogo: string // Ruta al logo
i18nDirectory: string // Directorio para traducciones i18n
localeDirectory: string // Directorio para useLocales JSONs
layoutDirectory: string // Directorio para layouts específicos
exclusivePages?: LayoutPage[] // Páginas activas para esta vertical
services: CommonServices & SpecificServices // Todos los servicios
strapiService: string // Nombre en Strapi
analyticsCode?: string // Google Analytics
searchConsoleCode?: string // Google Search Console
zohoConfig?: ZohoConfig // Config CRM
}

app/core/config.ts
import { INSPIRIA } from '~/constants/verticals/inspiria'
export const VERTICAL_LIST = [INSPIRIA]
export const visibleVertical = { ...selectVertical(VERTICAL_LIST) }

selectVertical() determina cuál vertical mostrar basándose en:

  • Desarrollo: Puerto del servidor (3000 = primera, 3001 = segunda, etc.)
  • Producción: Subdominio de la URL

// Servicios que TODAS las verticales deben implementar
interface CommonServices {
getCourses: FunctionService<...>
getUserLogin: FunctionService<...>
getCheckoutSession: FunctionService<...>
// ... 30+ servicios comunes
}
// Servicios que solo existen en verticales específicas
interface SpecificServices {
getChannels: FunctionService<...> // Solo Inspiria tiene channels
}

Cuando una vertical no implementa un servicio opcional, useServices no lo encuentra y retorna null.


  1. Crea app/constants/verticals/nueva-vertical.ts:
import type { Verticals } from '~/interfaces/verticals'
export const NUEVA_VERTICAL: Verticals = {
name: 'NuevaVertical',
subdomain: 'nueva',
productionApi: 'https://api.nueva-vertical.com',
developmentApi: 'http://localhost:1337',
productionURL: 'https://nueva-vertical.com',
primaryColor: '#FF6B35',
secondaryColor: '#1E3A5F',
favicon: '/favicons/nueva.ico',
verticalLogo: '/logos/nueva.svg',
i18nDirectory: 'nueva',
localeDirectory: 'nueva',
layoutDirectory: 'nueva',
exclusivePages: ['courses', 'lives'], // Solo estas páginas activas
services: {
// ... implementar todos los CommonServices
},
strapiService: 'nueva',
}
  1. Regístrala en app/core/config.ts:
export const VERTICAL_LIST = [INSPIRIA, NUEVA_VERTICAL]
  1. Crea traducciones en app/locales/nueva/es/, /en/, /pt-BR/

  2. La vertical estará disponible en el puerto siguiente (3001 en dev) o en su subdominio en producción.


visibleVertical es el objeto que todo el proyecto usa para acceder a la configuración de la vertical activa. Se importa desde ~/core/config:

import { visibleVertical } from '~/core/config'
// Acceder a servicios
visibleVertical.services.getCourses
// Acceder a configuración
visibleVertical.primaryColor
visibleVertical.productionApi