Docs

Motor de Invitaciones

Arquitectura del motor de generación de invitaciones, transiciones fullpage, loaders, particulas Canvas 2D e integración tematica.

PublicadoMarzo 2026Equipo de desarrollo, arquitectos, stakeholders

Arquitectura del Motor

El motor de invitaciones es el nucleo de generación de HTML en Nvito. Su responsabilidad es tomar la configuración de una invitación (secciones, estilos, datos del evento, transiciones, loaders) y producir un documento HTML completo, autocontenido y listo para servir desde CDN. El resultado final se almacena en S3 (MinIO en desarrollo, Cloudflare R2 en producción) como un conjunto de archivos HTML, CSS y JavaScript.

Flujo de Generación HTML

Componentes del Motor

ComponenteResponsabilidad
DocumentGeneratorServiceOrquestador principal. Coordina la compilacion de secciones, inyección de transiciones, loaders y particulas. Produce el documento HTML final y lo sube a S3.
TemplateCompilerServiceMotor de compilacion de templates. Resuelve variables ({{eventName}}), loops ({{#each items}}), condicionales ({{#if condition}}), e iconos ({{icon:calendar}}). Procesa en orden: loops primero, luego condicionales, luego iconos, y finalmente variables.
HtmlGenerationModuleModulo que toma las secciones individuales ya compiladas y las ensambla en un documento HTML completo con <head>, estilos globales, scripts, y la estructura de secciones fullpage.
TransitionEngineGenera el CSS y JavaScript necesario para las transiciones entre secciones. Soporta tanto transiciones CSS puras como transiciones Canvas 2D cinematograficas.
LoaderGeneratorProduce el HTML, CSS y JavaScript de la pantalla de carga que se muestra mientras la invitación carga sus recursos.
ParticleGeneratorGenera el código Canvas 2D para los 26 tipos de particulas utilizados por transiciones y loaders.

Almacenamiento en S3

El motor sube los archivos generados a un bucket S3 con la siguiente estructura:

invitations/
  {organizationId}/
    {invitationId}/
      index.html        # Documento HTML principal
      styles.css         # Estilos compilados del tema
      scripts.js         # JavaScript interactivo (RSVP, gallery, etc.)
      transitions.js     # Motor de transiciones (si aplica)
      loader.js          # Pantalla de carga (si aplica)

En desarrollo se utiliza MinIO como implementación local compatible con S3. En producción se utiliza Cloudflare R2, que ofrece compatibilidad con la API de S3 sin costos de egress.

Orden de Compilacion del TemplateCompiler

El TemplateCompilerService procesa el template en un orden estricto para evitar conflictos entre las distintas directivas:

  1. resolveLoops — Expande {{#each items}}...{{/each}} iterando sobre arrays del contexto. Resuelve {{this.campo}} dentro del loop.
  2. resolveConditionals — Evalua {{#if condición}}...{{/if}} y {{#unless condición}}...{{/unless}}. Remueve bloques no aplicables.
  3. resolveIcons — Reemplaza {{icon:nombre}} por el SVG correspondiente del catálogo de iconos.
  4. resolveVariables — Sustituye {{variable}} por el valor del contexto de datos del evento.

Este orden es critico: los loops deben resolverse primero porque pueden contener iconos anidados (por ejemplo {{icon:{{this.icon}}}} dentro de un {{#each}}). El loop resuelve {{this.icon}} a un nombre concreto, dejando {{icon:calendar}} que el paso de iconos procesa correctamente.


Secciones de Invitación

Cada invitación está compuestá por múltiples secciones, donde cada sección representa un bloque visual con un tipo específico, configuración JSON y un orden de aparicion. Las secciones son la unidad fundamental de composición del motor.

Tipos de Sección

TipoDescripciónConfiguración tipica
HeroSección principal con imagen de fondo, nombres de los anfitriones y fechaImagen, overlay, tipografia, layout
RSVPFormulario de confirmación de asistenciaCampos habilitados, texto de botones, opciones de acompanantes
LocationMapa y direccion del eventoCoordenadas, nombre del lugar, indicaciones, mapa embebido
ItineraryAgenda del evento con horarios y actividadesArray de items con hora, título, descripción, icono
GalleryGalería de fotosArray de URLs de imagenes, layout (grid/carousel/masonry)
CountdownCuenta regresiva al eventoFecha objetivo, formato de display, estilo visual
StoryHistoria de la pareja o contexto del eventoTexto enriquecido, imagenes opcionales
Dress CodeCódigo de vestimentaNivel de formalidad, colores, notas adicionales
Gift RegistryMesa de regalos con enlaces externosArray de items con nombre, URL, imagen
AccommodationInformación de hospedajeArray de hoteles con nombre, direccion, URL de reserva
CustomSección personalizada con HTML libreHTML del usuario, estilos custom

Modelo de Datos

Cada sección se almacena en la tabla InvitationSection con los siguientes campos principales:

CampoTipoDescripción
idUUIDIdentificador único
invitationIdUUIDReferencia a la invitación padre
typeenumTipo de sección (Hero, RSVP, etc.)
configJSONConfiguración específica del tipo
ordernumberPosición en la secuencia de secciones
visiblebooleanSi la sección se incluye en el render
titlestringTitulo opcional mostrado en la navegación

Restricciones

  • El número máximo de secciones depende del plan contratado por la organización.
  • Solo las secciones con visible: true se incluyen en el HTML generado.
  • La sección Hero siempre debe ser la primera (order = 0) y no puede ocultarse.
  • Las secciones se renderizan como páginas fullpage, donde cada sección ocupa el 100% del viewport y se navega entre ellas con scroll o transiciones.

Sistema de Transiciones Fullpage

El sistema de transiciones controla como se anima el cambio entre secciones cuando el usuario navega la invitación. Nvito ofrece 27 transiciones divididas en dos categorías: clasicas (CSS puro) y cinematograficas (Canvas 2D con motor de 3 fases).

Catálogo de Transiciones

Transiciones Clasicas (10) — CSS Only

NombreDescripciónDuracion Total
fadeDesvanecimiento suave entre secciones~1.1s
slideDeslizamiento horizontal/vertical~1.3s
curtainEfecto cortina que se abre/cierra~1.5s
wipeBarrido lineal que revela la siguiente sección~1.3s
zoomZoom in/out con desvanecimiento~1.4s
morphTransformacion fluida entre formas~1.5s
revealRevelado desde el centro hacia los bordes~1.3s
parallax-shiftMovimiento parallax con profundidad~1.5s
star-wipeBarrido en forma de estrella~1.7s
dissolveDisolución pixelada progresiva~1.4s

Transiciones Cinematograficas (17) — Canvas 2D + 3 Fases

NombreDescripciónTipo de Efecto
celestial-veilVelo de estrellas que cubre y descubreParticulas naturales
golden-sweepBarrido dorado con particulas brillantesParticulas naturales
petal-driftPetalos flotando durante la transiciónParticulas naturales
confetti-burstExplosion de confeti coloridoTematico (__tc)
leaf-cascadeCascada de hojas cayendoParticulas naturales
sacred-glowResplandor sagrado con halo de luzParticulas naturales
butterfly-waltzMariposas volando entre seccionesParticulas naturales
shimmer-veilVelo brillante con destellosTematico (__tc)
bubble-riseBurbujas ascendentesParticulas naturales
firework-bloomFuegos artificiales que florecenTematico (__tc)
feather-fallPlumas cayendo suavementeParticulas naturales
aurora-waveOnda de aurora borealParticulas naturales
neon-gridRejilla neon que se iluminaTematico (__tc)
rose-bloomPetalos de rosa abriendoseParticulas naturales
geometric-revealFormas geometricas que revelan (CSS-only)CSS
ink-bleedEfecto de tinta expandiendose (CSS-only)CSS
ribbon-unfurlCintas desenrollandose (CSS-only)CSS

Motor de 3 Fases

Las transiciones cinematograficas siguen un ciclo de 3 fases ejecutado por el TransitionEngine:

Detalle de las Fases

Fase CLOSE (IN: 0.9s) El overlay comienza a cubrir el viewport. Si la transición tiene Canvas, el efecto visual se inicia simultaneamente sobre el overlay. El usuario ya no puede interactuar con la sección actual. El Canvas se inicializa con requestAnimationFrame para renderizar el efecto a 60fps.

Fase STAMP (1.0s total) Una vez que el viewport está completamente cubierto, aparece el monograma del evento (iniciales de los anfitriones) con una animación de entrada (0.7s). Debajo del monograma se muestra el nombre de la sección destino. El monograma se mantiene visible brevemente y luego sale con una animación de desvanecimiento (0.6s).

Fase OPEN (OUT: 0.85s) El overlay sale de escena revelando la sección destino ya posicionada debajo. El Canvas se detiene y se limpia (cancelAnimationFrame + clear del contexto). Los event listeners temporales se remueven.

Timing Comparativo

AspectoClasicasCinematograficas
Duracion total~1.1 - 1.7s~2.75s
IN (entrada)0.55 - 0.9s0.9s
STAMPNo aplica1.0s
OUT (salida)0.5 - 0.8s0.85s
Easingcubic-bezier(0.4, 0, 0.2, 1)cubic-bezier(0.4, 0, 0.2, 1)
CanvasNoSi (excepto geometric-reveal, ink-bleed, ribbon-unfurl)

Modelo TransitionStyleDefinition

Cada transición se define como un objeto TransitionStyleDefinition con los siguientes campos:

CampoTipoDescripción
namestringIdentificador único de la transición
category'classic' | 'cinematic'Categoría de la transición
suggestedForstring[]Tipos de evento recomendados
overlayJsstringCódigo JavaScript del efecto Canvas (solo cinematograficas)
overlayHtmlstringHTML adicional para el overlay
stampHoldMsnumberDuracion del hold del monograma en milisegundos
hasCanvasbooleanSi la transición usa Canvas 2D
sectionLabelbooleanSi muestra el nombre de la sección destino

Pantallas de Carga (Loaders)

Las pantallas de carga se muestran mientras la invitación carga sus recursos (imagenes, fuentes, scripts). El loader debe dar una experiencia visual atractiva que mantenga la atencion del usuario durante los segundos iniciales.

Catálogo de Loaders

CSS Clasicos (8)

NombreDescripciónEstilo Visual
gold-calligraphyTexto caligrafico dorado con animación de escrituraElegante, bodas
celestial-starsEstrellas parpadeando sobre fondo oscuroNocturno, misterioso
mínimal-elegantLinea mínimalista con progresoModerno, limpio
festive-burstExplosion festiva de coloresFiestas, cumpleaños
romantic-petalsPetalos cayendo con suavidadRomantico, bodas
dark-cinematicBarra cinematografica con efecto filmicoSofisticado, galas
royal-ornamentOrnamentos reales con filigranaFormal, ceremonias
modern-glitchEfecto glitch digital con distorsionModerno, tech

Canvas 2D Cinematograficos (17)

NombreTipo de ColorDescripción
diamond-cascadeTematico (__tc)Cascada de diamantes brillantes
spiral-galaxyTematico (__tc)Galaxia espiral girando
watercolor-bloomTematico (__tc)Manchas de acuarela expandiendose
electric-pulseTematico (__tc)Pulsos electricos neon
sakura-windNatural (fijo)Flores de sakura en el viento
golden-dustTematico (__tc)Polvo dorado flotando
geometric-rainTematico (__tc)Lluvia de formas geometricas
lantern-glowTematico (__tc)Linternas flotantes brillando
confetti-showerTematico (__tc)Lluvia de confeti
ink-dropsNatural (fijo)Gotas de tinta expandiendose en agua
northern-lightsNatural (fijo)Aurora boreal ondulante
heartbeat-pulseNatural (fijo)Pulso de corazon con ondas
firefly-meadowNatural (fijo)Luciernagas en un prado nocturno
wave-horizonNatural (fijo)Olas en el horizonte
stained-glassNatural (fijo)Vitral iluminandose progresivamente
ticker-tapeTematico (__tc)Cinta de teletipo cayendo
cross-of-lightNatural (fijo)Cruz de luz expandiendose

Generación de Loaders

La función generateLoaderJs recibe un objeto LoaderStyleDefinition completo (no solo la duracion) y produce el código JavaScript que inicializa el loader. Para loaders Canvas, el código generado incluye:

  1. Inicializacion del Canvas — Crea el elemento <canvas>, lo dimensiona al viewport y obtiene el contexto 2D.
  2. Loop de animación — Usa requestAnimationFrame para renderizar particulas o efectos a 60fps.
  3. Barra de progreso — Superpuestá al efecto, muestra el porcentaje de carga real.
  4. Cleanup — Al completar la carga, detiene el loop, remueve el canvas y ejecuta la animación de salida.

Modelo LoaderStyleDefinition

CampoTipoDescripción
namestringIdentificador único del loader
category'classic' | 'cinematic'Categoría
hasCanvasbooleanSi usa Canvas 2D
canvasJsstringCódigo JavaScript del efecto Canvas
cssstringEstilos CSS del loader
htmlstringHTML del loader (estructura base)
progressBarobjectConfiguración de la barra de progreso (color, posición, estilo)

Responsividad y Accesibilidad

Los loaders Canvas implementan dos mecanismos de fallback para garantizar una buena experiencia en todos los dispositivos:

Mobile fallback: En pantallas menores a 640px de ancho, el Canvas se oculta y solo se muestra la versión CSS del loader. Esto evita problemas de rendimiento en dispositivos moviles con GPUs limitadas y reduce el consumo de bateria.

Reduced motion: Cuando el usuario tiene activada la preferencia prefers-reduced-motion: reduce en su sistema operativo, el Canvas se oculta completamente. La barra de progreso y el texto del loader se mantienen visibles pero sin animaciones, respetando la preferencia de accesibilidad del usuario.


Particulas Canvas 2D

El motor de particulas es un subsistema compartido por transiciones y loaders que proporciona 26 tipos de particulas con fisica, ciclo de vida y funciones de dibujo independientes. Cada tipo de particula está disenado para representar un elemento visual específico con comportamiento fisico realista.

Arquitectura del Motor de Particulas

Cada tipo de particula se define como un objeto con tres responsabilidades:

  1. init() — Inicializa la particula con posición, velocidad, tamano, color y propiedades específicas del tipo (rotación, opacidad, forma).
  2. update(dt) — Actualiza la fisica de la particula en cada frame: gravedad, resistencia del aire, rotación, desvanecimiento. Recibe dt (delta time) para animación independiente del framerate.
  3. draw(ctx) — Dibuja la particula en el contexto Canvas 2D usando las primitivas apropiadas (arcos, paths, bezier curves, imagenes).

Catálogo de 26 Tipos de Particulas

#TipoDescripciónUsado por
1PetaloPetalos de flor con rotación 3D simuladapetal-drift, rose-bloom
2HojaHojas de arbol con caida realistaleaf-cascade
3EstrellaEstrellas de 5 puntas con brillo pulsantecelestial-veil, celestial-stars
4ConfetiRectangulos de colores con giro biaxialconfetti-burst, confetti-shower
5MariposaMariposas con aleteo sinusoidalbutterfly-waltz
6BurbujaEsferas translucidas con reflejobubble-rise
7PlumaPlumas con caida flotante y balanceofeather-fall
8DestelloPuntos de luz con parpadeo aleatoriogolden-sweep, golden-dust
9Fuego artificialExplosion radial con trailsfirework-bloom
10RosaPetalos de rosa con apertura progresivarose-bloom
11NeonSegmentos de linea con glowneon-grid
12ShimmerFragmentos brillantes con ondulacionshimmer-veil
13SakuraFlor de cerezo con 5 petalos definidossakura-wind
14DiamantePoligonos facetados con refraccióndiamond-cascade
15GalaxiaPuntos orbitales en espiralspiral-galaxy
16AcuarelaManchas difusas con blendingwatercolor-bloom
17PulsoOndas concentricas expandiendoseelectric-pulse, heartbeat-pulse
18GeometriaTriangulos, circulos y cuadradosgeometric-rain
19LinternaOvalo luminoso con halo suavelantern-glow
20TintaGotas con expansion radial difusaink-drops
21AuroraBandas ondulantes con gradientenorthern-lights, aurora-wave
22LuciernagaPuntos con trail fosforescentefirefly-meadow
23OlaCurvas sinusoidales con crestáwave-horizon
24VitralPoligonos con bordes oscuros y relleno translucidostained-glass
25TickerRectangulos estrechos cayendo en cascadaticker-tape
26Cruz de luzRayos cruzados con expansion gradualcross-of-light

Ciclo de Vida de una Particula

Cuando una particula "muere" (opacidad llega a 0 o sale completamente del viewport), se marca como inactiva y se remueve del array de particulas activas. El motor puede opcionalmente reciclar particulas muertas (respawn) si la transición o loader lo requiere para mantener una densidad visual constante.


Theme Color Bridge

El Theme Color Bridge es el subsistema que conecta los colores del tema de la invitación con los efectos Canvas 2D. Su proposito es que las transiciones y loaders cinematograficos se integren visualmente con el esquema de colores elegido por el usuario, manteniendo coherencia estetica sin sacrificar la identidad visual de particulas naturales.

Arquitectura

Funcionamiento

El archivo utils/theme-color-bridge.ts se ejecuta al iniciar la invitación y realiza las siguientes operaciones:

  1. Lectura de CSS variables — Lee las variables CSS del tema (--t-overlay, --t-accent, --t-accent-light, --t-background, --t-primary) del elemento root del documento.
  2. Conversión a RGB arrays — Convierte cada color hexadecimal o HSL a un array [R, G, B] (valores 0-255) para uso directo en el Canvas 2D.
  3. Exposición global — Almacena los colores en window.__tc (theme colors) como un objeto con propiedades: overlay, accent, accentLight, background, primary. Cada propiedad es un array [number, number, number].

El bridge se inyecta en dos puntos:

  • loader-base.js.ts — Para que los Canvas loaders accedan a __tc durante su inicialización.
  • transition-engine.ts — Para que las Canvas transiciones accedan a __tc al crear particulas.

Principio de Diseño: Paleta Derivada con Identidad Preservada

El bridge sigue un principio de diseño fundamental: las particulas que representan elementos naturales reconocibles mantienen sus colores reales, mientras que los elementos artificiales o abstractos adoptan la paleta del tema.

La razon es cognitiva: un petalo rosa, una hoja verde o una luciernaga amarilla son reconocibles por su color natural. Cambiar esos colores para "encajar" con el tema romperia la ilusion y haria que las particulas se vean genericas. En cambio, el confeti, las formas geometricas, las ondas neon o los destellos no tienen un color "correcto" inherente, por lo que se benefician de adoptar la paleta del tema para crear una experiencia visualmente integrada.

Clasificación de Canvas Loaders

9 loaders tematicos (usan __tc del tema):

LoaderPor que es tematico
diamond-cascadeDiamantes abstractos, sin color natural inherente
spiral-galaxyGalaxia estilizada, colores arbitrarios
watercolor-bloomManchas de acuarela, cualquier color es válido
electric-pulsePulsos electricos, color definido por estetica
golden-dustPolvo brillante, adaptable a cualquier paleta
geometric-rainFormas geometricas puras, sin referente natural
lantern-glowLinternas estilizadas, color ambiental
confetti-showerConfeti, inherentemente multicolor y adaptable
ticker-tapeCinta de papel, sin color fijo

8 loaders con colores naturales fijos (NO usan __tc):

LoaderPor que es natural
sakura-windFlores de cerezo: siempre rosa palido
firefly-meadowLuciernagas: siempre amarillo-verde fosforescente
northern-lightsAurora boreal: siempre verde-azul-violeta
heartbeat-pulseLatido de corazon: siempre rojo
cross-of-lightLuz: siempre blanco-dorado
wave-horizonOlas del mar: siempre azul-turquesa
ink-dropsTinta: siempre negro-gris oscuro
stained-glassVitral: paleta fija multi-color clasica

Clasificación de Canvas Transiciones

4 transiciones tematicas (usan __tc):

  • shimmer-veil — Destellos abstractos, color adaptable
  • neon-grid — Rejilla neon, color definido por el tema
  • firework-bloom — Fuegos artificiales, multicolor adaptable
  • confetti-burst — Explosion de confeti, inherentemente tematico

10 transiciones con colores naturales fijos (NO usan __tc):

  • petal-drift — Petalos: rosa y blanco
  • leaf-cascade — Hojas: verdes y marrones
  • butterfly-waltz — Mariposas: colores de alas naturales
  • feather-fall — Plumas: blancas y crema
  • bubble-rise — Burbujas: translucidas con reflejo azulado
  • rose-bloom — Rosa: rojo y rosa
  • sacred-glow — Luz sagrada: dorado y blanco
  • celestial-veil — Estrellas: blanco y plateado
  • golden-sweep — Destellos dorados: siempre dorado
  • aurora-wave — Aurora: verde-azul-violeta natural

Integración con CSS

Además del bridge para Canvas, los componentes CSS de transiciones y loaders utilizan variables CSS directamente con fallbacks:

/* Ejemplo de transición CSS tematizada */
.overlay-background {
  background-color: var(--t-overlay, #0a0a0a);
}

.accent-glow {
  color: var(--t-accent, #d4af37);
  box-shadow: 0 0 20px var(--t-accent-light, rgba(212, 175, 55, 0.3));
}

/* Barra de progreso tematizada en todos los loaders */
.progress-bar {
  background-color: var(--t-accent, #d4af37);
}

Esto garantiza que incluso si el JavaScript del bridge no se ejecuta (por ejemplo, con JavaScript deshabilitado), los estilos CSS tienen fallbacks razonables que mantienen la coherencia visual.


Personalización por Invitado

El motor soporta personalización de contenido por invitado a nivel de loader (pantalla de carga) y sección RSVP, utilizando un sistema de shortCodes únicos que vincula cada URL de invitación con un invitado específico.

Arquitectura

Cada invitado puede recibir una URL personalizada con el parametro ?t={shortCode}, donde shortCode es un identificador de 12 caracteres generado con crypto.randomBytes (71 bits de entropia, URL-safe). El shortCode se almacena en el modelo GuestAccessToken (campo shortCode, único por invitación).

Al abrir la invitación, el JavaScript inyectado en el HTML ejecuta el siguiente flujo:

  1. Extracción del shortCode — Lee el parametro ?t= de la URL actual.
  2. Llamada al endpoint públicoGET /v1/invitations/public/guest/{shortCode} retorna datos NO sensibles del invitado: firstName, lastName, title, groupSize.
  3. Inyección en el loader — El nombre con título formal (ej: "Bienvenido, Ing. Juan") se muestra durante la pantalla de carga usando textContent (prevencion XSS).
  4. Inyección en la sección RSVP — Un saludo personalizado (ej: "Ing. Juan, confirma tu asistencia") se muestra en la cabecera del formulario RSVP.
  5. Fallback generico — Si no hay shortCode, si el endpoint falla, o si el invitado no se encuentra, se muestran textos genericos configurables desde el editor.

Textos Configurables

Los textos de personalización son editables desde nvito-admin a traves del editor de invitaciones:

SecciónCampoEjemplo con invitadoFallback generico
LoaderloaderGreeting"Bienvenido, Ing. Juan""Bienvenido"
RSVPrsvpGreeting"Ing. Juan, confirma tu asistencia""Confirma tu asistencia"

Los templates de texto soportan el placeholder {guestName} que se resuelve en el cliente con el nombre completo del invitado (incluyendo título si existe).

Restricciones de Personalización

  • El nombre del invitado solo se muestra en el loader y la sección RSVP. Las secciones hero y welcome NO muestran datos del invitado.
  • Solo se exponen campos no sensibles: nombre, apellido, título y tamano de grupo. Email y teléfono nunca se envian al cliente.
  • La personalización es 100% client-side: el HTML generado es identico para todos los invitados, y la resolución del nombre ocurre en JavaScript.
  • Si el shortCode es invalido, está inactivo o ha expirado, el endpoint retorna 404 y se usan los textos de fallback.
  • La inyección de texto usa textContent en lugar de innerHTML para prevenir XSS.

Botón "Agregar al Calendario"

El motor genera un botón flotante de tipo position: fixed en la esquina inferior derecha de la invitación que permite al invitado agregar el evento a su calendario. El botón muestra el texto "Agendar" con contraste dinámico calculado a partir del color de fondo del tema. El color se determina en tiempo de ejecución para garantizar legibilidad (WCAG AA).

Retrocompatibilidad

La feature es 100% retrocompatible. Las invitaciones que no incluyen ?t= en la URL funcionan normalmente mostrando los textos de fallback generico. El endpoint público de resolución de shortCode no afecta el rendimiento de invitaciones sin personalización porque la llamada solo se ejecuta si el parametro ?t= está presente.


Invitaciones Externas

Las invitaciones externas permiten a los usuarios subir HTML disenado fuera de Nvito y publicarlo a traves de la misma infraestructura de entrega (CDN, analiticas, RSVP). El motor diferencia entre invitaciones internas y externas a traves del enum InvitationSource.

Enum InvitationSource

ValorDescripción
INTERNALInvitación creada con el motor de templates y el editor visual de Nvito (default)
EXTERNALHTML disenado externamente, cargado por el usuario

HtmlValidatorService

El HtmlValidatorService ejecuta 9 pasos de validación sobre el HTML externo antes de permitir su almacenamiento:

PasoValidaciónMotivo
1Tamano máximoEl archivo no puede exceder 5MB
2HTML validoEl documento debe tener estructura HTML básica (html, head, body)
3Sin scripts peligrososRechaza script tags con src externo y llamadas a funciones de ejecución dinámica de código
4Sin iframes externosRechaza iframes apuntando a dominios no permitidos
5Sin formularios externosRechaza forms con action apuntando a dominios no permitidos
6Sin event handlers inlineRechaza onclick, onerror, onload y otros event handlers en atributos HTML
7Sin CSS imports externosRechaza @import url() apuntando a dominios no permitidos
8Encoding correctoEl documento debe estar en UTF-8
9Sin contenido ofensivoValidación básica de contenido (opcional, configurable)

Flujo de Upload

Comportamiento Condicional en Publicación

Cuando una invitación externa se aprueba y publica, el flujo de publicación tiene una diferencia clave respecto a las invitaciones internas:

  • INTERNAL: El DocumentGeneratorService genera el HTML completo a partir de las secciones, lo compila, le inyecta transiciones/loaders/analiticas, y lo sube a S3.
  • EXTERNAL: El motor omite la generación HTML (ya existe en S3). Solo inyecta el snippet de analiticas en el HTML existente para tracking de visitas y RSVP.

Otros comportamientos condicionales:

  • Edicion de secciones: Bloqueada para invitaciones externas (no tienen secciones editables).
  • Versiónamiento: Deshabilitado (siempre versión 1). Para actualizar, el usuario hace re-upload del HTML completo.
  • Transiciones y loaders: No aplican (el HTML externo maneja su propia navegación).
  • IA conversacional: No disponible para invitaciones externas.

Testing

El motor de invitaciones cuenta con una cobertura de tests exhaustiva que cubre transiciones, loaders, integración tematica, el validador HTML y el compilador de templates.

Resumen de Tests

AreaTestsCobertura
Transiciones (clasicas + cinematograficas)278Todas las 27 transiciones, timing, fases, Canvas init/cleanup
Loaders (CSS + Canvas)351Todos los 25 loaders, barra de progreso, responsividad, reduced motion
Integración tematica200Bridge __tc, 9 loaders tematicos, 8 naturales, 4 transiciones tematicas, 10 naturales
Total motor de invitaciones829-

Que se Prueba

Transiciones:

  • Cada transición genera CSS/JS valido
  • Las fases CLOSE/STAMP/OPEN respetan el timing configurado
  • Canvas init y cleanup se ejecutan correctamente
  • El monograma y el label de sección se renderizan
  • Los 14 tipos de evento de Nvito tienen al menos una transición sugerida

Loaders:

  • Cada loader genera HTML/CSS/JS valido
  • La barra de progreso refleja el porcentaje de carga
  • Mobile fallback oculta Canvas en pantallas menores a 640px
  • Reduced motion oculta Canvas con prefers-reduced-motion
  • generateLoaderJs recibe LoaderStyleDefinition completo

Integración tematica:

  • El bridge lee correctamente las CSS variables --t-*
  • Los 9 loaders tematicos usan __tc para sus colores
  • Los 8 loaders naturales NO usan __tc (colores fijos verificados)
  • Las 4 transiciones tematicas usan __tc
  • Las 10 transiciones naturales NO usan __tc
  • Los 14 tipos de evento tienen cobertura tematica

HtmlValidatorService:

  • 37 tests cubriendo los 9 pasos de validación
  • Vectores de ataque XSS reales
  • HTML malformado, encoding incorrecto, tamano excesivo

Referencias

Motor de Generación

  • DocumentGeneratorService: src/modules/invitations/services/document-generator.service.ts
  • TemplateCompilerService: src/modules/invitations/services/template-compiler.service.ts
  • HtmlGenerationModule: src/modules/invitations/html-generation/

Transiciones

  • TransitionEngine: src/modules/invitations/transitions/transition-engine.ts
  • Definiciones de transiciones: src/modules/invitations/transitions/definitions/
  • Tests: src/modules/invitations/transitions/__tests__/

Loaders

  • LoaderGenerator: src/modules/invitations/loaders/loader-generator.ts
  • Definiciones de loaders: src/modules/invitations/loaders/definitions/
  • Tests: src/modules/invitations/loaders/__tests__/

Particulas

  • ParticleGenerator: src/modules/invitations/particles/
  • 26 tipos: src/modules/invitations/particles/types/

Theme Bridge

  • theme-color-bridge.ts: src/modules/invitations/utils/theme-color-bridge.ts

Personalización por Invitado

  • GuestAccessToken: prisma/schema.prisma — Modelo con campo shortCode
  • Endpoint público: src/modules/invitations/controllers/invitations.controller.tsGET /v1/invitations/public/guest/:shortCode
  • Dispatchers: src/modules/invitations/services/ — Generación de shortCodes y URLs personalizadas

Invitaciones Externas

  • HtmlValidatorService: src/modules/invitations/services/html-validator.service.ts
  • ExternalInvitationService: src/modules/invitations/services/external-invitation.service.ts
  • ExternalInvitationController: src/modules/invitations/controllers/external-invitation.controller.ts

Documentación Relacionada

Esta pagina fue util?