Saltar al contenido principal

Educación superior técnico-profesional · 26 sedes en Chile · ~6.000 trabajadores y miles de estudiantes · Desarrollo Web

Desafío PEI — AIEP

"Desafío PEI" es un juego tipo Kahoot construido a medida para que AIEP evaluara —en vivo, simultáneamente y en todo Chile— el entendimiento de su nuevo Plan Educativo Institucional. Soportó 600-700 trabajadores conectados desde 26 sedes en un único evento, sin caídas, sin WebSockets, y con un admin que orquestaba el flujo desde una pantalla.

Next.js 15React 19TypeScriptTailwind CSS 4shadcn/uiPrisma 7PostgreSQLBetter AuthTanStack FormZod 4MotionRechartsReact ConfettiSonnerk6 (load testing)Vercel

Cliente

AIEP — Instituto Profesional

Duración

≈2 meses entre kickoff y evento oficial (octubre–diciembre 2025), con teaser previo de validación en noviembre. Proyecto cerrado tras el evento.

En producción

17 de diciembre 2025 — fecha del evento oficial nacional, con dos sesiones (mañana y tarde) y sets de preguntas distintos para cada una.

Mi rol

Desarrollo end-to-end + acompañamiento durante el evento en vivo

Usuarios

Multi-rol: Participantes (trabajadores AIEP) + Administrador del evento (control central)

Mockup ilustrativo. El sistema real es privado por acuerdo con el cliente — sin capturas ni datos reales.

El problema

Comunicar un PEI a 6.000 personas no es lo mismo que enviar un PDF.

AIEP estaba lanzando su nuevo Plan Educativo Institucional 2025-2029 y necesitaba que todos sus trabajadores —repartidos en 26 sedes a lo largo de Chile— lo conocieran y, sobre todo, lo entendieran. Mandar un correo con un adjunto y rezar no era opción: necesitaban un mecanismo que generara atención real y permitiera medir el entendimiento.

Un evento corporativo nacional pide una sola toma sin segunda oportunidad.

La activación se planeó como un evento en vivo único, transmitido a todas las sedes en paralelo, en dos sesiones (mañana y tarde). Sin retries: si el sistema fallaba durante el evento, no había ventana para arreglarlo. La capacidad esperada era de 600 a 700 personas concurrentes, pero el techo había que dejarlo más alto.

Kahoot resolvía el formato, pero no el control.

Los productos genéricos de quiz en vivo (Kahoot, Mentimeter) cubrían el formato base, pero no permitían el grado de control narrativo, branding, segmentación por sede ni el flujo específico que AIEP necesitaba: pausas de revisión, ranking por sede, sets distintos por sesión, sorteo con criterios propios y exportes para RRHH posteriores.

Y el tiempo era el tiempo.

Desde la decisión hasta el evento había ≈2 meses. Suficiente para construir bien, pero no para experimentar con infraestructura cara o riesgosa. La decisión técnica tenía que privilegiar lo que más probabilidades tenía de funcionar el día D.

La solución

Un Kahoot a medida, con la operación que el cliente realmente necesitaba.

Construimos una plataforma propia con dos roles: Participante (vista de juego) y Administrador (control central). El admin orquesta el evento en vivo desde un dashboard: activa cada pregunta cuando corresponde, ve la distribución de respuestas en tiempo real, muestra el ranking por sede en las pausas y dispara el sorteo final entre quienes obtuvieron 10/10.

Polling cada 2-4 segundos en lugar de WebSockets — y funcionó.

La decisión técnica más importante del proyecto fue NO usar WebSockets ni Ably. Para una trivia con preguntas de 60 segundos, una latencia de sincronización de 2-4 segundos es invisible para el usuario, y reduce drásticamente la complejidad operativa: cero infraestructura adicional, menos puntos de falla, costo cercano a cero, debugging trivial. Lo validamos con un load test de k6 simulando 1.000 usuarios concurrentes antes del evento.

UX pensada para evento corporativo real, no para una demo.

Tres decisiones de UX deliberadas: (1) Sin feedback inmediato — el participante no sabe si acertó hasta el final, evitando el abandono temprano que mata el engagement; (2) Entrada tardía permitida — quienes se conectan en la pregunta 5 pueden responder de la 1 a la 5 y sincronizarse, sin penalizar atrasos típicos de eventos corporativos; (3) Pregunta bonus para los que no llegaron a 10/10, manteniendo el juego activo hasta el final para todos.

Dos sets de preguntas, dos sesiones, mismo sistema.

El evento se hizo en dos turnos (mañana y tarde) con sets de preguntas distintos para evitar contaminación entre sesiones. El sistema soporta múltiples GameSession activas en paralelo, cada una con su questionSet (AM/PM) y su propio flujo de control, sin lógica especial.

El día del evento: cero incidentes técnicos.

El 17 de diciembre 2025 corrieron las dos sesiones con 600-700 conectados cada una. El sistema operó sin caídas, sin glitches de sincronización, sin tener que tocar el código en vivo. El admin manejó todo el evento desde un único panel.

En números

600-700

participantes en vivo

Conectados simultáneamente en cada sesión, desde 26 sedes en todo Chile.

1.000 VUs

validados con load test

k6 simuló 1.000 usuarios concurrentes con p(95) < 500ms antes del evento.

0

incidentes durante el evento

Las dos sesiones del 17/dic/2025 corrieron sin caídas ni glitches.

2 + 2

sesiones / sets de preguntas

Mañana y tarde con preguntas distintas, mismo sistema, sin lógica especial.

Arquitectura

Aplicación Next.js 15 (App Router, Turbopack) con React 19 y TypeScript estricto, desplegada en Vercel. Persistencia en PostgreSQL vía Prisma 7 con el driver adapter de pg. Autenticación con Better Auth (validación de correos @aiep.cl). La sincronización de estado de juego se hace por polling: cada cliente consulta `getActiveGameSession()` cada 2-4 segundos vía Server Actions, recuperando la pregunta activa, el tiempo restante y el estado de la sesión. El admin tiene acciones server-side dedicadas (`activateQuestion`, `moveToNextQuestion`, `resumeFromReview`, `moveToRaffle`) que actualizan la GameSession y disparan la actualización implícita en todos los clientes via su próximo poll. Validación end-to-end con Zod compartida entre cliente y server. Stats por sede calculadas server-side con queries Prisma agregadas y renderizadas con Recharts. Carga validada con k6 antes del evento: 1.000 VUs, p(95) bajo 500ms.

Cada elección técnica respondió al constraint dominante: el evento era una sola toma, sin segunda oportunidad. Privilegiamos lo conocido y validado sobre lo novedoso.

Decisiones técnicas

Next.js 15 + Server Actions

Backend liviano

Sin API REST separada: cada acción del admin (activar pregunta, mover al siguiente, sortear) y del participante (responder, refetchar estado) corre como Server Action tipada end-to-end. Para un evento puntual es lo más simple posible — sin servicio aparte, sin contratos duplicados.

Polling 2-4s en lugar de WebSockets

Pragmatismo

La decisión técnica más importante del proyecto. Para un quiz con preguntas de 60s, una latencia de 2-4s es invisible. WebSockets habría sumado infraestructura, costo y puntos de falla sin beneficio perceptible.

Prisma 7 + PostgreSQL

Integridad

Las respuestas no podían duplicarse ni perderse. Constraints únicos en (sessionId, userId, questionId) garantizan en base que una persona no responde dos veces la misma pregunta — la app no tiene que adivinar.

Better Auth

Identidad propia

Validación de correos institucionales @aiep.cl + esquema de roles propio sin lock-in a un SaaS de identidad. Para un cliente educativo grande, los datos de usuarios no se mandan a terceros.

k6 load testing

Validación previa

Antes del evento corrimos un load test simulando 1.000 VUs durante 10 minutos contra los endpoints críticos. Validó que el polling escalaba sin sobrecargar Postgres y que el p(95) quedaba bajo 500ms. Sin ese test, el polling era una apuesta — con ese test, fue una decisión informada.

TanStack Form + Zod 4

Validación compartida

Mismo schema Zod en el formulario de registro del participante y en la Server Action que lo procesa. Nada llega a la DB sin validar dos veces con la misma fuente de verdad.

shadcn/ui + Tailwind 4 + Motion

UI

Componentes accesibles con control total del estilo. Motion para transiciones entre estados (pregunta → pausa → resultados), React Confetti para el momento del ganador. UX cuidada en cada transición — esto se proyectaba en vivo a 26 sedes.

Recharts

Stats en vivo

Gráficos de barras con la distribución de respuestas por opción y el ranking de sedes, actualizados en el dashboard del admin durante las pausas de revisión.

Vercel

Deploy

Auto-deploy desde main, preview por PR, integración nativa con Vercel Analytics. Para un evento con fecha fija, la tranquilidad de saber que cada push está deployado en segundos vale oro.

Funcionalidades

Polling vs WebSockets — y por qué ganó

Sincronización del estado del juego mediante polling cada 2-4 segundos a Server Actions de Next.js. Sin infraestructura de WebSockets, sin servicio externo, sin estado en memoria. Validado con k6 hasta 1.000 usuarios concurrentes con p(95) bajo 500ms.

Admin con control narrativo del evento

Dashboard que orquesta el evento en vivo: activa cada pregunta manualmente, ve la distribución de respuestas en tiempo real, controla las pausas de revisión (después de P4 y P8), muestra ranking por sede y dispara el sorteo final. Una sola persona maneja todo el evento desde una pantalla.

Sin feedback inmediato (anti-abandono)

El participante no sabe si acertó hasta el final del juego. Decisión deliberada para evitar que las personas que fallan temprano se desconecten — todos llegan al final con la sensación de poder ganar. Aumenta el engagement de punta a punta.

Entrada tardía inteligente

Quienes se conectan después del inicio pueden responder desde la pregunta 1 hasta la que está activa. El sistema los sincroniza automáticamente. En eventos corporativos las llegadas tarde son inevitables — penalizarlas era penalizar la participación.

Ranking por sede en pausas

Después de las preguntas 4 y 8 el evento pausa para mostrar el ranking de las 26 sedes según % de respuestas correctas. Genera competencia interna entre campus y mantiene la atención cuando podría caer.

Sorteo final + pregunta bonus

Quienes obtienen 10/10 entran al sorteo aleatorio del premio principal. Quienes no llegaron a 10/10 acceden a una pregunta bonus de consolación, evitando que el juego termine como derrota para la mayoría.

Línea de tiempo

  1. Octubre 2025

    Kickoff

    Definición de scope, arquitectura sobre Next.js + Postgres y decisión clave de polling vs WebSockets. Primeras vistas y modelo de datos.

  2. Noviembre 2025

    Teaser de validación

    Lanzamiento de un teaser previo con 3 preguntas y reintentos para validar UX, copy y comportamiento bajo concurrencia real antes del evento oficial.

  3. Diciembre 2025

    Sprint final + load testing

    Admin dashboard completo, ranking por sede, sistema de sorteo, dos sets de preguntas. Load test con k6 simulando 1.000 usuarios concurrentes.

  4. 17 Dic 2025

    Evento oficial — dos sesiones

    Sesiones 11:00 y 16:00 con 600-700 trabajadores conectados desde 26 sedes. Sistema operó sin caídas durante el evento en vivo.

¿Tienes un proyecto similar?

Construyo sistemas a medida de extremo a extremo. Conversemos.