
Cómo construí un Kiosko para eventos del AWS Student Builder Group con HTML, Amplify y EmailJS
por Fernando Gutiérrez — AWS Student Builder Group at Instituto Tecnológico de Ocotlán 💜 En nuestro grupo AWS Student Builder Group at ITO CardenalITO's queríamos una experiencia diferente para los asistentes de nuestros eventos: que pudieran tomarse una foto, agregarle stickers con la identidad visual del programa, y recibirla por correo. Sin frameworks, sin backend complejo — solo HTML puro, AWS Amplify y EmailJS. Te cuento cómo lo construimos, los retos que enfrentamos y qué aprendimos en el camino.
El problema
En el AWS Student Builder Group at ITO Ocotlán organizamos eventos donde queremos que los asistentes se lleven algo más que conocimiento. Queríamos una experiencia memorable: que cada persona pudiera tomarse una foto en el evento, personalizarla con stickers de la identidad visual del programa y recibirla directo en su correo.
Como en el eventos de la JSConf en el Both de AWS — donde vimos algo similar — pero construido por nosotros, con nuestra identidad, para nuestra comunidad.
Referencias al cual queria llegar

El reto: hacerlo sin presupuesto, sin dispositivos especiales y que funcionara desde cualquier teléfono o laptop en el evento.
La idea
Un kiosko digital accesible desde el browser. Sin instalar nada. Sin apps. Solo abrir un link.
La experiencia sería:
- Abrir la URL en tu teléfono o en una laptop del evento
- Tomar una foto con la cámara
- Agregar stickers de los iconos oficiales del SBG
- Activar el marco "AWS Student Builder Group"
- Descargar la foto o recibirla por correo
Simple en concepto. Interesante en ejecución.
Stack técnico
Decidí mantenerlo lo más simple posible:
Decidí mantenerlo lo más simple posible:
| Capa | Tecnología | Por qué |
|---|---|---|
| Frontend | HTML + CSS + JS vanilla | Sin frameworks, cero dependencias de build |
| Cámara | Web API getUserMedia | Nativa en todos los browsers modernos |
| Edición | HTML5 Canvas API | Para combinar foto + stickers en una imagen |
| Hosting | AWS Amplify | Deploy en segundos, URL pública, gratis |
| EmailJS | Sin backend, directo desde el browser | |
| Imágenes | ImgBB CDN | Para hostear los 60+ iconos sin peso en el repo |
Construyendo el Photo Booth
La cámara
Lo primero fue acceder a la cámara. Con la Web API getUserMedia es directo:
La cámara
Lo primero fue acceder a la cámara. Con la Web API getUserMedia es directo:
1
2
3
4
5
const stream = await navigator.mediaDevices.getUserMedia({
video: { facingMode: 'user', width: { ideal: 1280 } },
audio: false
});
video.srcObject = stream;
El video se muestra en vivo sobre el stage. Al tomar la foto se dibuja el frame del video en un <canvas>.
Los stickers arrastrables
Cada icono del SBG se coloca como un div absoluto sobre el stage con pointer-events y drag usando la Pointer API:
Cada icono del SBG se coloca como un div absoluto sobre el stage con pointer-events y drag usando la Pointer API:
1
2
3
4
5
6
el.addEventListener('pointerdown', (e) => {
state.activeSticker = el;
state.dragOffset.x = e.clientX - rect.left;
state.dragOffset.y = e.clientY - rect.top;
el.setPointerCapture(e.pointerId);
});
Esto funciona igual en mouse y touch — importante para que funcione en teléfono durante el evento.
También agregué un handle de resize en la esquina inferior derecha de cada sticker para que la gente pueda ajustar el tamaño.
El marco y el watermark
El marco es un overlay HTML con
position: absolute que se activa con un toggle. Al descargar, todo se aplana en un canvas con drawImage:1
2
3
// Logo AWS siempre en la foto - similar al marco del evento de la JSConf
await drawImg(ctx, 'https://i.ibb.co/Ng3GhCf7/AWS-smile-RGB-WHT.png',
stageW - 110, stageH - 54, 96, 40);
Logo AWS siempre en la foto - similar al marco del evento de la JSConf
Los retos reales
- El problema del file://
El primer obstáculo fue intentar probar la app abriéndola como archivo local. El browser bloquea fetch y getUserMedia desde file:// por políticas de seguridad.
Solución: Subir a AWS Amplify desde el principio y probar desde la URL pública.
- Espacios en nombres de archivo
Los assets del SBG tienen nombres como AWS Student Builder Group_RGB_Icons_Teams_Magenta.png. Los browsers no cargan imágenes con espacios en rutas locales.
Solución: Hostear todos los iconos en ImgBB y usar URLs directas. Eliminó el problema completamente y además el repo queda limpio y liviano.
- CORS duplicado en Lambda
Intenté primero con una Lambda en Python + Resend para el envío de correos. El error más frustrante fue este:
1
The 'Access-Control-Allow-Origin' header contains multiple values '*, *'
La Lambda retornaba el header CORS en el código Python y la Function URL de AWS lo agregaba automáticamente. Se duplicaban y Chrome lo rechazaba.
Solución: Quitar los headers CORS del código Python y dejar que AWS los maneje solo.
- Límite de 50KB en EmailJS
Al final migré a EmailJS para simplificar — sin Lambda, sin AWS para el correo. Pero EmailJS tiene un límite de 50KB por request y una foto en base64 pesa varios MB.
Solución: Comprimir la foto antes de enviarla:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function compressPhoto(dataUrl, maxSize, quality) {
return new Promise((resolve) => {
const img = new Image();
img.onload = () => {
const canvas = document.createElement('canvas');
const ratio = Math.min(maxSize / img.width, maxSize / img.height, 1);
canvas.width = Math.round(img.width * ratio);
canvas.height = Math.round(img.height * ratio);
canvas.getContext('2d').drawImage(img, 0, 0, canvas.width, canvas.height);
resolve(canvas.toDataURL('image/jpeg', quality));
};
img.src = dataUrl;
});
}
// Comprimir a 400px, calidad 50% → ~15-20KB
const compressed = await compressPhoto(photoDataUrl, 400, 0.5);
De varios MB a menos de 20KB. El correo llega con la foto incluida.
El resultado
Una app de una sola página (
index.html) que:- Abre la cámara del dispositivo
- Permite agregar 60+ stickers de la identidad visual del SBG en 7 colores
- Activa un marco oficial "AWS Student Builder Group"
- Descarga la foto con todos los elementos
- Envía la foto por correo con un mensaje personalizado:
"Hola [Nombre], Futuro Builder Member 💜 — Esta es tu foto del evento. ¡Saliste muy Guap@! Esperamos que te unas a nuestra comunidad."
Deploy: AWS Amplify — URL pública lista en minutos
Costo: $0
Costo: $0
Lo que aprendí
- HTML puro sigue siendo poderoso. Canvas API + Pointer API + getUserMedia hacen cosas que hace unos años requerían Flash o apps nativas.
- Simplificar la arquitectura ahorra horas. Empecé con Lambda + Resend + API Gateway. Terminé con EmailJS directo desde el browser. Menos piezas, menos problemas.
- Hostear assets en CDN desde el principio. Los nombres de archivo con espacios y el problema de
file://se resuelven solos cuando las imágenes viven en una URL. - AWS Amplify para static hosting es imbatible. ZIP, drag & drop, URL pública en 2 minutos
Links
Demo: https://staging.d2pm9uwh5z4g6s.amplifyapp.com
GitHub: https://github.com/EnderlotLG/aws-sbg-photobooth
AWS Student Builder Group at ITO CardenalITO's: https://builder.aws.com/community/student-builder-groups
Demo: https://staging.d2pm9uwh5z4g6s.amplifyapp.com
GitHub: https://github.com/EnderlotLG/aws-sbg-photobooth
AWS Student Builder Group at ITO CardenalITO's: https://builder.aws.com/community/student-builder-groups
Próximos pasos
Agregar modo galería para ver las fotos del evento en tiempo real
Integrar con AWS S3 para guardar las fotos
Versión multilingüe (EN/ES)
QR code en el evento para acceder directo desde el teléfono
Agregar modo galería para ver las fotos del evento en tiempo real
Integrar con AWS S3 para guardar las fotos
Versión multilingüe (EN/ES)
QR code en el evento para acceder directo desde el teléfono
Construido con Amor💜 para los CardenalITOs — AWS Student Builder Group at Instituto Tecnológico de Ocotlán & AWS Community Latam & AWS SBG WW
¿Tienes un grupo SBG y quieres usar esto en tu próximo evento? El código está en GitHub — fork it y personalízalo con tu identidad.
Te dejo unos ejemplos de las fotos del Photo Booth interactivo*:*






Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article