- Agregar puntaje final con badge color-coded según rangos - Agregar chips para categorías organolépticas (fragancia/aroma, sabor, gustos, sensación) - Agregar chips para todos los valores de intensidad (afectiva ❤️ y descriptiva 📊) - Agregar chips condicionales para tazas no uniformes (warning) - Agregar chips condicionales para tazas defectuosas con tipo de defecto (error) - Layout de dos líneas: header con #/nombre/puntaje y chips informativos - Diseño compacto y responsive
Plantilla Nuxt + Authentik Proxy
Plantilla base para aplicaciones Nuxt 4 con autenticación mediante Authentik Proxy Outpost.
Estructura del Proyecto
.
├── nuxt4/ # Aplicación Nuxt 4
├── docker-compose.yml # Configuración de despliegue
└── .gitea/ # Gitea Actions CI/CD
Características
- ✅ Nuxt 4
- ✅ Autenticación con Authentik Proxy Outpost
- ✅ Docker y Docker Compose
- ✅ CI/CD con Gitea Actions
- ✅ Traefik para proxy reverso y SSL
- ✅ Claude Code hooks para monitoreo de Actions
- ✅ Sin configuración OAuth necesaria (todo manejado por el proxy)
Desarrollo Local
cd nuxt4
npm install
npm run dev
Claude Code Hooks
Este proyecto incluye hooks de Claude Code para monitorear automáticamente las Gitea Actions.
Configuración Rápida:
-
Crear token de Gitea:
- Ve a tu instancia de Gitea → Settings → Applications
- Genera un token con permisos
repo
-
Configurar token:
echo "export GITEA_TOKEN='tu_token_aqui'" >> ~/.bashrc source ~/.bashrc -
Listo! Cuando Claude Code haga
git push, automáticamente:- Monitoreará la Gitea Action
- Te notificará cuando termine con información detallada
- Te mostrará un link directo a los logs
📖 Ver documentación completa en .claude/hooks/README.md
Arquitectura de Componentes
Componentes de Autenticación
La aplicación utiliza componentes Vue modulares para manejar la autenticación:
1. UserAvatar (app/components/auth/UserAvatar.vue)
- Muestra el avatar del usuario (generado por UI Avatars)
- Información básica: nombre/username, email y UID
- Se renderiza solo cuando el usuario está autenticado
2. UserMetadata (app/components/auth/UserMetadata.vue)
- Card detallada con todos los metadatos del usuario
- Muestra: username, email, nombre completo, UID y grupos
- Incluye badges para visualizar los grupos del usuario
3. Botones de Acción (componentes individuales)
Cada botón es un componente independiente con su propia lógica:
-
SessionStatusButton: Verifica el estado de la sesión contra Authentik
- Hace una petición a
/api/auth/status - Muestra notificaciones toast con el resultado
- Maneja casos offline y errores de conexión
- Hace una petición a
-
ProfileButton: Redirige al perfil de usuario en Authentik
- Abre el panel de usuario de Authentik en nueva pestaña
- URL:
{authentikUrl}/if/user/
-
LogoutButton: Cierra sesión en Authentik
- Invalida la sesión en todas las aplicaciones
- Redirige a:
{authentikUrl}/flows/-/default/invalidation/
-
LoginButton: Fuerza re-autenticación
- Recarga la página para activar el flujo de login de Authentik
Composable useAuthentik()
Composable centralizado para manejar autenticación (app/composables/useAuthentik.ts):
Funcionalidades:
- Lee headers de Authentik en el servidor (SSR)
- Almacena información del usuario en
useState(compartido entre cliente/servidor) - Proporciona funciones reactivas:
user,isAuthenticated - Métodos:
logout(),goToProfile(),checkSessionStatus()
Headers leídos del Proxy:
X-authentik-username // Nombre de usuario
X-authentik-email // Email
X-authentik-name // Nombre completo
X-authentik-groups // Grupos (separados por |)
X-authentik-uid // ID único del usuario
Despliegue
El proyecto incluye Gitea Actions que automáticamente:
- Construye la imagen Docker
- La sube al registro
- Despliega usando docker-compose
Variables Requeridas en Gitea
Para configurar el despliegue automático, ve a tu repositorio en Gitea:
- Secrets:
Settings > Actions > Secrets - Variables:
Settings > Actions > Variables
Secrets (valores sensibles):
REGISTRY_USERNAME- Usuario del registro DockerREGISTRY_PASSWORD- Contraseña del registro Docker
Variables (valores públicos):
REGISTRY_URL- URL del registro Docker (ej:gitea.nucleoriofrio.com)- El owner del repositorio se agrega automáticamente
- Imagen final:
REGISTRY_URL/owner/APP_NAME:latest
APP_NAME- Nombre de la aplicación (ej:mi-app) - usado para container, imagen y TraefikAPP_DOMAIN- Dominio de la aplicación (ej:miapp.ejemplo.com)NUXT_PUBLIC_APP_URL- URL pública de la app (ej:https://miapp.ejemplo.com)
📄 Ver ejemplo completo en .env.example
Configuración de Traefik y Authentik
🔐 Cómo Funciona Authentik Proxy Outpost
Authentik Proxy Outpost actúa como un Forward Auth middleware que intercepta todas las peticiones antes de que lleguen a tu aplicación:
Usuario → Traefik → Authentik Forward Auth → Aplicación Nuxt
↓ (si no auth)
Redirect a Login
Flujo de autenticación:
- Usuario hace petición → Traefik recibe la petición a tu dominio
- Traefik consulta Authentik → Envía la petición al middleware de Forward Auth
- Authentik valida sesión:
- ✅ Con sesión válida: Authentik agrega headers con info del usuario y envía la petición a tu app
- ❌ Sin sesión: Authentik redirige al usuario al flujo de login
- Tu app recibe la petición → Con headers de usuario ya inyectados (SSR)
Ventajas:
- ✅ No necesitas implementar OAuth en tu app
- ✅ La autenticación se maneja completamente fuera de tu código
- ✅ Los headers llegan automáticamente en cada petición SSR
- ✅ Funciona con cualquier framework (Nuxt, Next.js, PHP, etc.)
🚦 Configuración de Reglas de Traefik
El docker-compose.yml configura dos routers en Traefik para balancear seguridad y funcionalidad PWA:
Router 1: Rutas Públicas (Sin Autenticación) - Prioridad 100
# Rutas que NO requieren autenticación
- PathPrefix(`/manifest.webmanifest`) # Manifest PWA
- PathPrefix(`/sw.js`) # Service Worker
- PathPrefix(`/workbox-`) # Workbox (PWA)
- PathPrefix(`/icon-`) # Iconos de la app
- PathPrefix(`/apple-touch-icon`) # Icono iOS
- PathPrefix(`/favicon.ico`) # Favicon
- PathPrefix(`/robots.txt`) # SEO
- PathPrefix(`/offline.html`) # Página offline PWA
- PathPrefix(`/api/_nuxt_icon/`) # API de iconos de Nuxt
Middlewares aplicados:
${APP_NAME}-headers: Headers personalizados (X-Forwarded-Proto)${APP_NAME}-cors: Configuración CORS para recursos públicos
¿Por qué sin autenticación?
- Los Service Workers necesitan acceso sin auth para funcionar offline
- Los manifests PWA deben ser públicos para instalación
- Prioridad 100 asegura que estas rutas se evalúen primero
Router 2: Aplicación Protegida (Con Autenticación) - Prioridad 10
# Todas las demás rutas (Host match)
Host(`${APP_DOMAIN}`)
Middlewares aplicados:
authentik-forward-auth@file: Forward Auth de Authentik${APP_NAME}-headers: Headers personalizados
Características:
- Prioridad menor (10) → se evalúa después de las rutas públicas
- Cualquier ruta no pública pasa por autenticación
- Authentik inyecta headers con información del usuario
📋 Configuración de Authentik Proxy Outpost
Requisitos previos:
- Traefik corriendo con las redes
traefik-networkyprincipal - Authentik instalado y funcionando
Pasos de configuración:
1. Crear el Middleware en Traefik
Crea o edita el archivo de configuración dinámica de Traefik (ej: dynamic/middlewares.yml):
http:
middlewares:
authentik-forward-auth:
forwardAuth:
address: http://authentik-server:9000/outpost.goauthentik.io/auth/traefik
trustForwardHeader: true
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
- X-authentik-email
- X-authentik-name
- X-authentik-uid
Importante: Cambia authentik-server por el nombre de tu contenedor/servicio de Authentik.
2. Configurar Authentik
a) Crear un Proxy Provider:
- Ve a Admin > Applications > Providers
- Click en Create
- Tipo: Proxy Provider
- Configuración:
- Name:
Mi App - Forward Auth - Authorization flow: Selecciona tu flujo (ej:
default-provider-authorization-implicit-consent) - Type:
Forward auth (single application) - External host:
https://miapp.ejemplo.com(tu dominio)
- Name:
b) Crear una Application:
- Ve a Admin > Applications > Applications
- Click en Create
- Configuración:
- Name:
Mi App - Slug:
mi-app - Provider: Selecciona el provider creado arriba
- Name:
c) Vincular al Outpost:
- Ve a Admin > Outposts > Outposts
- Edita tu Outpost (o crea uno nuevo si no existe)
- En Applications: Agrega la aplicación creada
3. Configurar las Redes en Docker Compose
Tu aplicación necesita estar en ambas redes:
networks:
principal: # Red de tu infraestructura
external: true
traefik-network: # Red donde corre Traefik
external: true
Asegúrate de que estas redes existan:
docker network create principal
docker network create traefik-network
🔍 Headers Disponibles en tu Aplicación
Una vez configurado, Authentik inyecta estos headers en cada petición:
| Header | Descripción | Ejemplo |
|---|---|---|
X-authentik-username |
Nombre de usuario | nucleo000 |
X-authentik-email |
Email del usuario | user@example.com |
X-authentik-name |
Nombre completo | John Doe |
X-authentik-groups |
Grupos (separados por |) |
admins|users |
X-authentik-uid |
ID único del usuario | 703cae063c59... |
En Nuxt, estos headers se leen automáticamente en SSR mediante useRequestHeaders().
🐛 Troubleshooting
Problema: "Cannot find name 'process'"
- ✅ Usa
import.meta.serveren lugar deprocess.server(Nuxt 4)
Problema: Redirect loop infinito
- Verifica que el middleware
authentik-forward-auth@fileesté correctamente configurado - Revisa que la aplicación esté asociada al Outpost en Authentik
- Comprueba que el External host coincida con tu dominio
Problema: Headers no llegan a la aplicación
- Verifica que
authResponseHeadersincluya todos los headers necesarios - Asegúrate de que estés leyendo headers en SSR (
import.meta.server)
Problema: PWA no funciona offline
- Verifica que las rutas públicas tengan prioridad 100
- Confirma que
/sw.js,/manifest.webmanifesty/offline.htmlestén en el router público
Licencia
MIT