Hands-on Serverless: Your First Cloud App with AWS Lambda

Construye y despliega una app de tareas en AWS con Lambda, API Gateway, DynamoDB y S3, paso a paso desde la consola y sin administrar servidores.
alejojaimes/ajteaches-tutorials
memecam-workshop
Una app que reconoce tus gestos con MediaPipe y te responde con un meme, montada en AWS con Lambda, API Gateway, DynamoDB, S3 y Amplify, sin un solo servidor que administrar.
Hola, estimado lector :). Para seguir este tutorial basta con saber programar lo básico en Python o JavaScript y haber abierto una terminal alguna vez. No hace falta tener cuenta de AWS: crearla es el primer paso. Si nunca ha tocado la nube, mejor. La mayoría desconoce que es, y la forma más rápida de conocerla es construir algo que uno quiera mostrarle a los amigos.
1. Introducción
¿Qué aprenderás?
A montar el backend de una app con una función Lambda por cada acción, lo que se conoce como arquitectura de lambdas. En el camino aparecen dos ideas que se usan todo el tiempo en la industria: las URLs prefirmadas, para que el navegador suba y baje archivos de S3 sin exponer el bucket, y las Lambdas disparadas por eventos, que se ejecutan solas cuando pasa algo en la nube.
¿Qué construirás?
MemeCam: abres la página, activas la cámara y cada gesto que haces (abrir la boca, sonreír, mostrar el puño, tocarte la cabeza…) muestra un meme distinto. Cada asistente puede cambiar los memes por los suyos, y un ranking en vivo muestra qué gestos se usan más en el salón.

¿Cómo lo harás?
Paso a paso, desde la consola web de AWS. La detección corre en el navegador con MediaPipe y el video nunca sale del computador: a la nube solo llega el nombre del gesto. ¡Manos a la obra!

2. Contexto de la App
¿Qué es serverless y qué es una Lambda?
En una app tradicional, el backend vive en un servidor que alguien tiene que encender, actualizar y pagar las 24 horas, aunque nadie lo esté usando a las 3 de la mañana. Serverless no significa que no haya servidores. Significa que de ellos se encarga el proveedor de la nube, y uno solo escribe el código.

AWS Lambda es el servicio de AWS que lleva esa idea a lo más simple. Una Lambda es una función: un archivo con código que se ejecuta solo cuando algo la llama y se apaga al terminar. Ese “algo” se llama evento y puede ser una petición HTTP, un archivo nuevo en un bucket o una tarea programada, entre otros.

def lambda_handler(event, context):
# event trae lo que disparó la función: el body de una petición,
# el nombre del archivo que llegó a S3, etc.
return {"statusCode": 200, "body": "Hola desde Lambda"}Lo que cambia en la práctica:
- Se paga por uso. AWS cobra por cada invocación y por los milisegundos que dura. Si nadie usa la app, el costo es cero. Además, el primer millón de invocaciones al mes es gratis.
- Escala sola. Si una persona usa la app, corre una copia de la función. Si la usan cien al mismo tiempo, AWS levanta las copias que hagan falta, sin configurar nada.
- Cada función hace una cosa. Por eso en MemeCam hay cinco: una para listar memes, otra para contar gestos, etc.
También tiene sus límites. Una Lambda puede correr máximo 15 minutos, no guarda nada entre una ejecución y otra (por eso los datos van a DynamoDB y las imágenes a S3), y la primera llamada después de un rato sin uso tarda un poco más mientras AWS la prepara. A eso se le llama cold start, y se ve en el paso 11.
Pipeline de la app

El recorrido completo funciona así:
1. El usuario abre la página publicada en Amplify Hosting, que la sirve con HTTPS. Sin HTTPS el navegador no deja usar la cámara.
2. MediaPipe analiza el video en el navegador. Si gestures.js decide que hay un gesto, muestra el meme y le avisa a la API con fetch().
3. API Gateway recibe la petición y llama a la Lambda de esa ruta.
4. Las Lambdas leen y escriben en DynamoDB: qué meme corresponde a cada gesto y cuántas veces se ha hecho.
5. Las imágenes viven en un bucket de S3 privado. El navegador las descarga y sube directamente, con permisos temporales que firma una Lambda.
6. Cuando llega una imagen nueva a S3, el propio S3 dispara la Lambda register-meme, que la registra en DynamoDB.
Ruta o evento | Función Lambda | Qué hace |
|---|---|---|
|
| Devuelve los memes con URLs prefirmadas |
|
| Da permiso temporal para subir un meme |
S3 |
| Registra en DynamoDB cada imagen subida |
|
| Suma 1 al gesto detectado |
|
| Devuelve el ranking de gestos |
¿Qué es MediaPipe?

MediaPipe es una librería de código abierto de Google para visión por computador en tiempo real. Trae modelos ya entrenados que se usan con unas pocas líneas de código: no hay que recolectar fotos, entrenar nada ni saber de redes neuronales.
Con ella se puede, por ejemplo:
- Ubicar 468 puntos de la cara y medir expresiones, como qué tanto está abierta la boca o si la persona sonríe.
- Seguir los 21 puntos de cada mano y reconocer gestos como el puño cerrado o el pulgar arriba.
- Detectar la postura del cuerpo completo, que es lo que usan muchas apps de ejercicio para contar repeticiones.
- Encontrar objetos en una imagen o separar a una persona del fondo, como hacen los fondos virtuales de las videollamadas.
Funciona en Python, en Android, en iOS y en el navegador. Esta última versión es la que usa MemeCam: el modelo se descarga una vez y corre en el computador de quien abre la página, sin mandar el video a ningún servidor. Eso explica por qué la detección es instantánea y por qué la nube, en esta app, solo se entera del nombre del gesto.
¿Cómo detecta los gestos?

MediaPipe entrega dos tipos de información en cada frame:
- Face Landmarker devuelve 468 puntos de la cara y 52 blendshapes: números entre 0 y 1 que dicen qué tanto está abierta la mandíbula, qué tanto sonríe cada comisura, etc.
- Gesture Recognizer devuelve los 21 puntos de cada mano y un gesto ya clasificado (
Closed_Fist,Thumb_Up,Open_Palm…).
Con eso, gestures.js decide así:
Gesto | Cómo se detecta |
|---|---|
Abrir la boca | Blendshape |
Sonreír | Promedio de |
Mostrar el puño | Una mano con |
Mostrar los dos puños | Dos manos con |
Pulgar arriba | Una mano con |
Tocarse la cabeza | La punta de algún dedo está en la zona de la frente o la sien |
Inclinar la cabeza | La línea entre los ojos se inclina más de 18°, con la boca cerrada |
Cabeza hacia atrás | La nariz "sube" frente al mentón un 18 % respecto a la pose neutral |
El orden importa: primero se revisan las manos y después la cara, porque un gesto con la mano casi siempre es intencional. Además, un gesto solo se activa si se mantiene 5 frames seguidos, para que el meme no parpadee con cada movimiento.
¿Por qué MediaPipe corre en el navegador y no en una Lambda?
Se podría enviar cada frame a una Lambda y que ella detectara el gesto. Haciendo cuentas sale más rápido: a 30 frames por segundo, con 30 personas usando la app serían 900 invocaciones por segundo, cada una con la cara de alguien viajando a la nube. Y el meme llegaría con medio segundo de retraso, que en una app de reacciones arruina el chiste.
En el navegador, en cambio, la detección no tarda nada y no cuesta nada. La nube queda para lo que el navegador no puede hacer solo: guardar los memes, compartirlos entre todos y llevar la cuenta de los gestos. Así funcionan la mayoría de apps reales con visión por computador.
¿Por qué una Lambda por ruta?
Se podría meter todo en una sola función con un if por ruta, y para algo de este tamaño funcionaría. Separarlas tiene una ventaja que se nota el primer día que algo falla: si el ranking no carga, el problema está en un archivo de 30 líneas y en su propio log group de CloudWatch, no enterrado entre los logs de las otras rutas.
Además, register-meme ni siquiera tiene ruta: la dispara S3. Eso sería incómodo de meter dentro de una función que también atiende peticiones HTTP.
Tiene su contra, claro: son cinco cosas que configurar en vez de una, y en el paso 7 se va a sentir un poco repetitivo. Vale la pena igual.
3. Antes de Empezar
Descargar el código
Todo el código está listo en el repositorio memecam-workshop.
Para descargarlo con Git:
git clone https://github.com/alejojaimes/ajteaches-tutorials.git
cd ajteaches-tutorials/memecam-workshopSin Git, también sirve el botón Code → Download ZIP de GitHub. Lo importante es tener la carpeta memecam-workshop en el computador, con esta estructura:
memecam-workshop/
│
├── frontend/
│ ├── index.html # interfaz
│ ├── app.js # cámara, MediaPipe y llamadas a la API
│ ├── gestures.js # lógica que decide qué gesto estás haciendo
│ ├── config.js # aquí va la URL de la API
│ └── memes/ # los 8 memes, nombrados por gesto
│ ├── open_mouth.jpg
│ ├── smile.jpg
│ ├── fist.jpg
│ ├── head_tilt.jpg
│ ├── touch_head.jpg
│ ├── head_back.jpg
│ ├── two_fists.jpg
│ └── thumbs_up.jpg
│
├── lambdas/
│ ├── register_meme/lambda_function.py
│ ├── list_memes/lambda_function.py
│ ├── get_upload_url/lambda_function.py
│ ├── track_event/lambda_function.py
│ └── get_stats/lambda_function.py
│
├── test-events/ # eventos para probar cada Lambda en la consola
│
└── iam/
├── memecam_lambda_policy.json
└── s3_cors.jsonRuta del tutorial
- Crear la cuenta de AWS
- Alerta de presupuesto
- Convenciones y tags
- MemeCam en local
- Bucket S3 para los memes
- Tabla en DynamoDB
- Rol IAM para las Lambdas
- Las funciones Lambda
- API con API Gateway
- Probar la API con curl
- Publicar MemeCam en Amplify Hosting
- Ranking en vivo y logs en CloudWatch
- Limpieza de recursos
Del paso 3 en adelante, cada paso lleva a la nube una parte de lo que ya funciona en local.
Con este contexto claro, vamos a ir guiándonos paso a paso.
4. Paso a paso
Paso 1: Crear la cuenta de AWS
Desde julio de 2025, al registrarse AWS pide elegir entre un Free plan y un Paid plan. Ambos arrancan con 100 USD en créditos. El Free plan dura 6 meses (o hasta gastar los créditos) y después la cuenta se cierra sola si no se cambia a Paid, así que nunca cobra a la tarjeta. Para este tutorial el Free plan es la opción recomendada.
1. Entrar a aws y hacer clic en Create a free account.

2. Escribir el correo electrónico y un AWS account name (por ejemplo: mi-cuenta-aws). Hacer clic en Verify email address.

3. Revisar el correo, copiar el código de verificación y pegarlo en el formulario.

4. Crear la contraseña del usuario root. Es la llave maestra de la cuenta, debe ser fuerte y guardarse en un gestor de contraseñas.

5. Seleccionar el plan Free plan.

6. Completar la información de contacto. En el tipo de cuenta seleccionar Personal.

7. Ingresar los datos de una tarjeta de crédito o débito. AWS hace un cargo temporal pequeño para verificarla y luego lo reversa.

Si se queda cargando y llega la validación de que se consultó la tarjeta de crédito. Devolverse en la flecha superior izquierda e ir a "Consola" o "signin". Luego dar clic en cerrar sesión, y volver a iniciar con correo y contraseña.
8. Hacer clic en Complete sign up y esperar el correo de confirmación.
9. Iniciar sesión con usuario y contraseña. Para eso, elegir la opción Sign in using root user email.



Ingresar código de verificación que llega al correo. Dar clic en Verify and continue


Para la validación con MFA es opcional. Se recomienda usar Passlwy o Authenticator App. Para efectos de esta práctica daremos clic en Skip for now.

Validar el acceso a la consola de AWS

En la esquina superior cambiar la región a
us-east-1o (Norte de Virginia)
Paso 2: Alerta de presupuesto
Aunque el Free plan no cobra a la tarjeta, la alerta de presupuesto es un hábito que conviene tener desde el día uno: avisa por correo si algo empieza a consumir créditos sin que uno lo note.
1. En la barra de búsqueda superior, escribir Billing and Cost Management (Administración de facturación y costos) y hacer clic en el resultado.

2. En el menú lateral izquierdo, hacer clic en Budgets (Presupuestos).

3. Hacer clic en el botón naranja Create budget.

4. En Budget setup, seleccionar Use a template (simplified).

5. En Templates, seleccionar Monthly cost budget.

6. Completar los campos:
- Budget name: memecam-workshop-budget-cietaxviii
- Enter your budgeted amount ($): 2.00
- Email recipients: el correo electrónico

7. Hacer clic en Create budget.


Paso 3: Convenciones y tags
Todos los recursos del tutorial llevan el mismo prefijo y las mismas tags. Al final, cuando toque borrarlo todo, se agradece poder encontrarlos sin adivinar.
- Prefijo del proyecto: memecam
- Región: us-east-1 (N. Virginia). Antes de cada paso, verificar en la esquina superior derecha de la consola que la región sea la misma. Es el error más común: crear la tabla en una región y la Lambda en otra.
- Nombre del bucket: debe ser único en todo AWS. Formato recomendado: memecam-memes-<iniciales>-01, por ejemplo memecam-memes-jac-01.
Tags que deben añadirse en cada recurso que lo permita:
Key | Value |
|---|---|
|
|
|
|
|
|
|
|
Paso 4: MemCam en Local
Antes de tocar la nube, vale la pena ver la app funcionando. En modo local (con API_URL vacío en config.js) MemeCam usa las imágenes de la carpeta memes/ y lleva el conteo en memoria. Así, el resto del tutorial tiene un objetivo claro: llevar esto a la nube.
Desde la carpeta del proyecto:
cd frontend
python -m http.server 8000
Abrir localhost en Chrome o Edge y hacer clic en Activar cámara.


💡 La cámara solo funciona en páginas
https://o enlocalhost. Por eso no sirve abrir elindex.htmlcon doble clic: hay que servirlo conhttp.server.
Algunas cosas para probar:
1. Mirar a la cámara con cara neutral durante un segundo. La app usa ese momento para aprender cómo se ve tu cabeza "derecha", que es la referencia para el gesto de cabeza hacia atrás.

2. Hacer cada uno de los 8 gestos. La tarjeta del gesto se ilumina y aparece el meme.

3. Guiñar un ojo o usar el botón Tomar captura. Hay 3 segundos de cuenta regresiva para alcanzar a hacer un gesto, y la foto aparece en el panel Capturas, lista para descargar. Desde ahí también se puede borrar cada captura o vaciar el panel completo.


4.Hacer clic en Debug (esquina superior derecha) para ver los números que MediaPipe calcula en vivo: qué tanto está abierta la boca, el ángulo de la cabeza, el gesto de cada mano y qué tan cerrado está cada ojo.

Paso 5: Bucket S3 para los memes
Este bucket es privado: nadie puede ver su contenido con un link directo. El navegador solo accede a través de URLs temporales que firman las Lambdas.
4.1 Crear el bucket
1. En la barra de búsqueda superior, escribir S3 y hacer clic en el servicio.

2. Hacer clic en Create bucket.
3. En Bucket name, escribir: memecam-memes-<iniciales>-01

4. Verificar que la región sea us-east-1.
5. En Block Public Access settings for this bucket, dejar todo marcado. No se toca.
6. En la sección Tags, añadir las 4 tags del Step 2.

7. Hacer clic en Create bucket.

4.2 Configurar CORS del bucket
El navegador va a subir y descargar archivos directamente desde S3, que es un dominio distinto al de la app. Igual que pasa con la API, S3 tiene que decir explícitamente que acepta esas llamadas.
1. Entrar al bucket y abrir la pestaña Permissions.

2. Bajar hasta Cross-origin resource sharing (CORS) y hacer clic en Edit.

3. Pegar el contenido de iam/s3_cors.json:
[
{
"AllowedOrigins": ["*"],
"AllowedMethods": ["GET", "POST"],
"AllowedHeaders": ["*"],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
}
]Hacer clic en save changes.

Para pensar: que el bucket permita CORS desde cualquier origen no lo vuelve público. CORS solo le dice al navegador que puede hacer la llamada; S3 igual exige una firma válida en cada petición.
Paso 6: Tabla en DynamoDB
La tabla tiene una fila por gesto. La misma fila guarda qué imagen le corresponde y cuántas veces se ha detectado, guardará algo como esto:
{
"gestureId": "smile",
"label": "Sonreír",
"imageKey": "memes/smile.jpg",
"count": 42,
"updatedAt": "2026-10-21T19:37:35+00:00"
}1. En la barra de búsqueda superior, escribir DynamoDB y hacer clic en el servicio.

2. En el menú lateral izquierdo, hacer clic en Tables.
3. Hacer clic en el botón naranja Create table.

4. Completar:
- Table name: memecam-gestures
- Partition key: gestureId, tipo String
- Sort key: dejar vacío

5. En Table settings, dejar Default settings (capacidad On-demand: se paga por solicitud).

6. Bajar hasta la sección Tags y añadir las 4 tags del Step 2.

7. Hacer clic en Create table y esperar a que el estado sea Active.

6.1 Copiar el ARN de la tabla
1. Hacer clic en el nombre de la tabla.

2. En la pestaña Overview, desplegar Additional info.

3. Copiar el Amazon Resource Name (ARN). Tiene esta forma:
arn:aws:dynamodb:us-east-1:123456789012:table/memecam-gesturesy pegarlo en un bloc de notas. Lo usaremos más adelante.
Paso 7: Rol IAM para las Lambdas
Las cinco Lambdas comparten un rol con tres permisos:
Permiso | Para qué |
|---|---|
| Escribir logs en CloudWatch (administrada por AWS) |
DynamoDB sobre | Leer, actualizar y listar las filas de la tabla |
S3 sobre | Leer y escribir solo dentro de la carpeta |
7.1 Crear el rol
1. En la barra de búsqueda, escribir IAM y hacer clic en el servicio.

2. En el menú lateral izquierdo, hacer clic en Roles.

3. Hacer clic en el botón naranja Create role.

4. En Trusted entity type, seleccionar AWS service.

5. En Use case, seleccionar Lambda y hacer clic en Next.

6. Buscar AWSLambdaBasicExecutionRole, marcar su checkbox y hacer clic en Next.

7. En Role name, escribir: memecam-lambda-role

8. En la sección Tags, añadir las 4 tags del Step 2.

9. Hacer clic en Create role.

7.2 Agregar los permisos de DynamoDB y S3
1. Abrir el rol memecam-lambda-role.

2. En la pestaña Permissions, hacer clic en Add permissions → Create inline policy.

3. Cambiar el editor de Visual a JSON.

4. Borrar todo y pegar iam/memecam_lambda_policy.json, reemplazando <ARN_DE_LA_TABLA> por el ARN del Step 5 y <NOMBRE_DEL_BUCKET> por el nombre del bucket del Step 4:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GesturesTable",
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:UpdateItem",
"dynamodb:Scan"
],
"Resource": "arn:aws:dynamodb:us-east-1:92****:table/memecam-gestures"
},
{
"Sid": "MemesBucket",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::memecam-memes-aj-01/memes/*"
}
]
}

5. Hacer clic en Next, escribir el nombre memecam-access y hacer clic en Create policy.


Importante: una URL prefirmada tiene exactamente los permisos de quien la firmó. Si a este rol le falta
s3:GetObject, la Lambda va a generar URLs sin quejarse, pero el navegador recibiráAccessDeniedal abrirlas. Es uno de los errores más confusos de todo el tutorial, por eso vale la pena entenderlo desde ya.
Paso 8: Las funciones Lambda
Este es el paso más largo. Son cinco funciones con casi la misma configuración y distinto código, así que la primera se hace con calma y las demás salen rápido.
Cada función se crea igual:
1. En la barra de búsqueda, escribir Lambda y hacer clic en el servicio.

2. Hacer clic en Create function → Author from scratch.

3. Completar:
- Function name: el de la tabla de abajo
- Runtime: la versión más reciente de Python 3 disponible (por ejemplo, Python 3.13)
- Architecture: x86_64
4. Desplegar Change default execution role, seleccionar Use an existing role y elegir memecam-lambda-role.

5. Hacer clic en Create function.

6. En la pestaña Code, borrar el contenido de lambda_function.py, pegar el código correspondiente y hacer clic en Deploy.

7. En Configuration → Environment variables → Edit, agregar las variables de la tabla y hacer clic en Save.



8. En Configuration → Tags, añadir las 4 tags del Step 2.
Function name | Código | Variables de entorno |
|---|---|---|
|
|
|
|
|
|
| |
|
|
|
|
|
|
|
Valores: TABLE_NAME = memecam-gestures y BUCKET_NAME = el nombre del bucket del Step 4.
9. Repetir el mismo proceso, para la creación del resto de las funciones.
8.1 memecam-register-meme: la Lambda que dispara S3
Esta función no tiene ruta en la API. Se ejecuta sola cada vez que llega un archivo a la carpeta memes/ del bucket, lee el nombre del archivo (smile.jpg → gesto smile) y lo registra en la tabla.

Después de crearla:
1. En la página de la función, hacer clic en Add trigger.

2. En el selector de origen, elegir S3.
3. En Bucket, seleccionar memecam-memes-<iniciales>-01.
4. En Event types, dejar All object create events.
5. En Prefix, escribir memes/
6. Marcar la casilla de confirmación sobre Recursive invocation.
7. Hacer clic en Add.

Subir los memes y ver cómo se llena la tabla
Esta es mi parte favorita del tutorial: aquí se ve la arquitectura orientada a eventos funcionando sin escribir una línea más de código.
1. Ir a S3 → el bucket → Create folder → nombre memes → Create folder.
2. Entrar a la carpeta memes/ → Upload → Add files.
3. Seleccionar las 8 imágenes de frontend/memes/ y hacer clic en Upload.
4. Ir a DynamoDB → Tables → memecam-gestures → Explore table items.

7.2 memecam-list-memes: URLs prefirmadas para descargar
El bucket es privado, así que el navegador no puede pedir memes/smile.jpg directamente. Esta función recorre la tabla y, por cada gesto, firma una URL temporal que funciona durante una hora.
Para probarla: pestaña Test → Create new event → nombre listar → pegar test-events/list_memes.json → Save → Test. En la respuesta aparecen las 8 URLs; al copiar una en el navegador, se ve el meme.
7.3 memecam-upload-url: permiso temporal para subir
Cuando alguien quiere cambiar un meme por uno propio, el archivo no pasa por la Lambda. La Lambda solo entrega un POST prefirmado: un permiso de 5 minutos para subir una imagen, a una ruta exacta, de máximo 5 MB. El navegador sube el archivo directo a S3 y el trigger de la 7.1 se encarga del resto.
Para pensar: ¿por qué no recibir la imagen en la Lambda y que ella la guarde en S3? Porque API Gateway limita el tamaño de las peticiones, la Lambda cobraría por todo el tiempo de la subida y el archivo viajaría dos veces. Con el POST prefirmado la Lambda tarda milisegundos y el archivo va directo a su destino
7.4 memecam-track-event: contar gestos
Cada vez que el navegador confirma un gesto, llama a esta función para sumar 1 al contador.
Importante: el truco está en ADD #count :one. Si en vez de eso se leyera el contador, se le sumara 1 en Python y se guardara, dos personas sonriendo al mismo tiempo leerían el mismo valor y una de las dos sonrisas se perdería. ADD hace la suma dentro de DynamoDB, de forma atómica. Cuando la app se comparte y mucha gente la usa a la vez, la diferencia se nota.
7.5 memecam-get-stats: el ranking
Probarla con test-events/get_stats.json. El gesto que se probó en la 7.4 debe aparecer de primero.
Paso 8: API con API Gateway
API Gateway le pone una URL pública a las cuatro Lambdas que atienden peticiones: recibe la petición, mira el método y la ruta, y llama a la función que corresponde. Se usa el tipo HTTP API; REST API tiene más opciones, pero es más cara y para esta app no se necesita ninguna de ellas.
8.1 Crear la API e integrar las Lambdas
1. En la barra de búsqueda, escribir API Gateway y hacer clic en el servicio.

2. Hacer clic en Create API.

3. En la tarjeta HTTP API, hacer clic en Build.
4. Hacer clic en Add integration, seleccionar Lambda y elegir memecam-list-memes.
5. Repetir Add integration con memecam-upload-url, memecam-track-event y memecam-get-stats. (register-meme no va aquí: la dispara S3).

6. En API name, escribir: memecam-api
7. Hacer clic en Next.
8.2 Configurar las rutas
1. Para cada fila, seleccionar el Method, escribir el Resource path y verificar el Integration target.
Method | Resource Path | Integration target |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
2. Hacer clic en Next.
3. En Configure stages, dejar $default con Auto-deploy activado y hacer clic en Next.
4. Hacer clic en Create.

5. Copiar el Invoke URL de la página de la API. Tiene esta forma:


8.3 Configurar CORS
1. En el menú lateral de la API, en Develop, hacer clic en CORS → Configure.

2. Completar:
- Access-Control-Allow-Origin: * (hacer clic en Add)
- Access-Control-Allow-Headers: content-type (hacer clic en Add)
- Access-Control-Allow-Methods: GET, POST y OPTIONS
3. Hacer clic en Save.

Para pensar:
*permite llamadas desde cualquier origen, y mientras se aprende está bien. Cuando la app esté publicada en Amplify, en producción se reemplazaría por el dominio exacto, por ejemplohttps://main.d1abc2xyz.amplifyapp.com.
Paso 9: Publicar MemeCam en Amplify Hosting
Para que cualquiera pueda abrir la app desde su celular hace falta publicarla con HTTPS, porque fuera de localhost el navegador no da acceso a la cámara en páginas http://. Amplify Hosting publica una carpeta de archivos estáticos con HTTPS y un dominio propio, y se despliega arrastrando un zip.
9.1 Conectar el frontend con la API
Abrir frontend/config.js y pegar el Invoke URL del Step 8, **sin / al final**:
export const API_URL = "https://abc123xyz.execute-api.us-east-1.amazonaws.com";Antes de publicar, se puede probar de nuevo en local con python -m http.server 8000. Ahora la etiqueta de arriba dice Nube (AWS), los memes llegan desde S3 y cada tarjeta tiene un botón Cambiar meme.

9.2 Empaquetar el frontend
El zip debe tener index.html en la raíz, no dentro de una carpeta frontend/. Por eso se comprime el contenido de la carpeta y no la carpeta:
# macOS / Linux
cd frontend
zip -r ../memecam-frontend.zip .
Alternativa para windows
# Windows PowerShell
Compress-Archive -Path frontend\* -DestinationPath memecam-frontend.zip9.3 Desplegar
1. En la barra de búsqueda, escribir Amplify y hacer clic en AWS Amplify.

2. Hacer clic en Create new app.

3. Seleccionar Deploy without Git y hacer clic en Next.

4. Completar:
- App name: memecam
- Branch name: main

5. En Method, dejar Drag and drop y arrastrar memecam-frontend.zip.

6. Hacer clic en Save and deploy.

7. Esperar a que el estado sea Deployed (menos de un minuto) y abrir el Domain, con esta forma:

https://main.d11rk7z8gic70q.amplifyapp.com/


Paso 10 : Ranking en vivo y logs en CloudWatch
Este es el momento de compartir el link de Amplify con amigos, compañeros o el grupo de WhatsApp de la familia. Cada persona abre la app en su celular o computador, activa la cámara y empieza a hacer gestos. El panel Ranking del salón se actualiza cada 4 segundos con los gestos de todos.

Ver los logs
Cada print() de las Lambdas queda guardado en CloudWatch Logs. Es la primera parada cuando algo falla.
1. Ir a Lambda → memecam-track-event.

2. Hacer clic en la pestaña Monitor y luego en View CloudWatch logs.

3. Abrir el log stream más reciente. Aparece una línea Gesto smile: 42 por cada gesto que alguien hizo.

Paso 11 : Limpieza de recursos
Esto debe hacerse al terminar. Aunque el costo es mínimo, dejar recursos huérfanos es mala práctica y, en una cuenta Paid, termina apareciendo en la factura.
El orden recomendado:
1. Amplify: abrir la app memecam → App settings → General settings → Delete app → confirmar escribiendo delete.
2. API Gateway: seleccionar memecam-api → Actions → Delete → confirmar.
3. Lambda: marcar las cinco funciones memecam-* → Actions → Delete → escribir confirm.
4. S3: entrar al bucket → seleccionar la carpeta memes/ → Delete → escribir permanently delete. Con el bucket vacío, volver a la lista → seleccionarlo → Delete → escribir el nombre del bucket.
5. DynamoDB: seleccionar memecam-gestures → Delete → escribir confirm.
6. IAM: en Roles, buscar memecam-lambda-role → Delete → escribir el nombre del rol.
7. CloudWatch: en Log groups, buscar /aws/lambda/memecam, marcar los cinco log groups → Actions → Delete log group(s).
8. Budget: puede dejarse (no tiene costo) o eliminarse desde Billing → Budgets.
¿Y ahora qué?
Ahora mismo cualquiera con el link puede cambiar los memes de todos, y apenas se comparte el link en un grupo, pasan unos cinco minutos antes de que alguien suba algo que no debería. Lo primero que yo agregaría es login con Amazon Cognito, para que cada persona tenga su propio set de memes y su propio ranking.
Lo segundo: después de crear cinco Lambdas, un bucket, una tabla y una API a mano, uno entiende rápido por qué existe la infraestructura como código. Eso da para otro tutorial.
Si leyó hasta aquí, gracias. De verdad.
Escribir esto tomó tiempo y saber que alguien lo lee hasta el final lo hace valer la pena. Si algo no quedó claro, tiene dudas o quiere debatir algún punto, queda la cajita de los comentarios. Leo todo (casi siempre jajaja).
Nos vemos en la próxima, espero que haya sido de mucha utilidad.
— Alejo 🥭
Comments (0)
Sign in to comment