Skip to content

Routing, Layouts y Middleware

Las rutas se generan automáticamente desde la estructura de app/pages/. No hay archivo de router manual.

ArchivoRuta
pages/index.vue/
pages/courses/index.vue/courses
pages/courses/[slug].vue/courses/:slug (dinámica)
pages/account/settings.vue/account/settings

Para crear una nueva ruta, solo crea el archivo .vue en la ubicación correcta.

El nombre [slug] crea un parámetro de ruta:

const route = useRoute()
const slug = route.params.slug // 'odontologia-avanzada'
const { data } = useServices('getCourseBySlug', { slug })

SecciónRutasDescripción
Home/Landing principal con sliders, destacados
Channels/channels, /channels/[slug]Canales de contenido por marca/partner
Courses/courses, /courses/[slug]Listado y detalle de cursos
Lives/lives, /lives/[slug]Eventos en vivo y grabaciones
Books/books, /books/[slug]Biblioteca digital (PDFs)
Presentials/presentials, /presentials/[slug]Cursos presenciales
Series/series/[slug]Series de video episódicas
Account/account/*Dashboard: perfil, historial, suscripción
Auth/iniciar-sesion, /registro, /recuperar-contrasenaLogin, registro, recovery
Osteocom/osteocom/*Productos de partners
Legal/aviso-legal, /politica-privacidad, /cookiesPáginas legales
Otros/empresa, /protagonistas, /faq, /soporteCompany, expertos, ayuda

Los layouts definen la estructura visual que envuelve una página (qué navbar mostrar, si hay footer, sidebars, etc.).

LayoutCuándo se usa
default(implícito) Navbar + contenido + Footer
baseProductDetailDetalle de producto con sidebar de acciones
gradientLayoutFondo con gradiente de marca (secciones hero)
emptyLayoutSin navbar ni footer (auth, landings especiales)
pages/accountDashboard del usuario con menú lateral
pages/loginLayout minimalista de login
pages/registerLayout de registro con pasos
pages/subscriptionPágina de planes de suscripción
definePageMeta({
layout: 'gradientLayout'
})

Si no defines layout, usa el default (navbar + footer).


Guards de navegación que se ejecutan antes de cargar una página. Pueden redirigir, bloquear, o ejecutar lógica.

Protege rutas privadas y previene acceso innecesario a login:

  • Si visita /account o /my-contents sin sesión válida → redirige a /iniciar-sesion + muestra alerta de sesión expirada
  • Si visita /iniciar-sesion o /registro estando logueado → redirige a home

Internamente llama authStore.validateSession() que verifica el JWT y determina el estado de suscripción.

Establece el idioma en cada navegación:

  1. Lee idioma guardado en localStorage
  2. Si no hay → detecta idioma del navegador (navigator.language)
  3. Normaliza a uno de los 3 soportados: es, en, pt-BR
  4. Aplica via languageStore.setLanguage()

Bloquea páginas que la vertical actual no tiene activas. Cada vertical define exclusivePages: ['books', 'presentials'] — si una vertical no incluye una página, este middleware la bloquea.

definePageMeta({
middleware: ['exclusive-pages']
})

Asegura que la página de “Gracias” solo se acceda tras completar una compra real (previene acceso directo por URL).


IdiomaURLPrefijo
Español (default)/cursosNinguno
Inglés/en/courses/en
Portugués/pt-BR/cursos/pt-BR

Estrategia: prefix_except_default — el idioma principal no tiene prefijo en la URL.

Definidas en app/config/i18n/pages.ts:

{
courses: {
es: '/cursos',
en: '/courses',
'pt-BR': '/cursos'
},
'courses/[slug]': {
es: '/cursos/[slug]',
en: '/courses/[slug]',
'pt-BR': '/cursos/[slug]'
}
}
const { t } = useI18n()
<h1>{{ t('courses.title') }}</h1>
<p>{{ t('common.no_results') }}</p>
const localePath = useLocalePath()
// Genera la ruta en el idioma actual del usuario
navigateTo(localePath('/courses'))
// Si el usuario está en inglés → /en/courses
// Si está en español → /cursos
i18n/ → Globales (compartidas entre verticales)
├── es.json
├── en.json
└── pt-BR.json
app/locales/inspiria/ → Específicas de la vertical Inspiria
├── es/
├── en/
└── pt-BR/

Para configurar metadata de una página:

definePageMeta({
layout: 'gradientLayout', // qué layout usar
middleware: ['exclusive-pages'], // middleware adicional
})

Configurados en nuxt.config.ts:

routeRules: {
'/formacion/**': { redirect: '/channels/normon' }
}

URLs antiguas se redirigen automáticamente a las nuevas.