TutorialPythonAWSCloudServerlessAWSLambdaApiGatewayDynamoDBS3Backend

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

A�
Alejandro Jaimes 🥭22 min read · 23 de octubre de 2026 · 02:54 p. m.
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.

Repositorio de GitHub

alejojaimes/ajteaches-tutorials

memecam-workshop

JavaScriptMIT0
Ver en GitHub

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.

Image by the author

¿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!

Image by the author

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.

Image by author

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.

AWS Lambda - Wikipedia
python
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

Image by author

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

GET /memes

memecam-list-memes

Devuelve los memes con URLs prefirmadas

POST /memes/upload-url

memecam-upload-url

Da permiso temporal para subir un meme

S3 ObjectCreated en memes/

memecam-register-meme

Registra en DynamoDB cada imagen subida

POST /events

memecam-track-event

Suma 1 al gesto detectado

GET /stats

memecam-get-stats

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?

face_landmark mediapipe

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 jawOpen mayor a 0.45

Sonreír

Promedio de mouthSmileLeft y mouthSmileRight mayor a 0.55

Mostrar el puño

Una mano con Closed_Fist

Mostrar los dos puños

Dos manos con Closed_Fist

Pulgar arriba

Una mano con Thumb_Up

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-workshop

Sin 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:

bash
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.json

Ruta del tutorial

  1. Crear la cuenta de AWS
  2. Alerta de presupuesto
  3. Convenciones y tags
  4. MemeCam en local
  5. Bucket S3 para los memes
  6. Tabla en DynamoDB
  7. Rol IAM para las Lambdas
  8. Las funciones Lambda
  9. API con API Gateway
  10. Probar la API con curl
  11. Publicar MemeCam en Amplify Hosting
  12. Ranking en vivo y logs en CloudWatch
  13. 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.

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

  1. 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.

  2. Validar el acceso a la consola de AWS

  3. En la esquina superior cambiar la región a us-east-1 o (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

Project

memecam-workshop

Environment

dev

Owner

<nombre>

ManagedBy

workshop-cietaxviii


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:

bash
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 en localhost. Por eso no sirve abrir el index.html con doble clic: hay que servirlo con http.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:

json
[
  {
    "AllowedOrigins": ["*"],
    "AllowedMethods": ["GET", "POST"],
    "AllowedHeaders": ["*"],
    "ExposeHeaders": [],
    "MaxAgeSeconds": 3000
  }
]
  1. 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:

json
{
  "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:

bash
arn:aws:dynamodb:us-east-1:123456789012:table/memecam-gestures

y 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é

AWSLambdaBasicExecutionRole

Escribir logs en CloudWatch (administrada por AWS)

DynamoDB sobre memecam-gestures

Leer, actualizar y listar las filas de la tabla

S3 sobre memes/* del bucket

Leer y escribir solo dentro de la carpeta memes/

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:

json
{
  "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á AccessDenied al 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

memecam-register-meme

lambdas/register_meme

TABLE_NAME

memecam-list-memes

lambdas/list_memes

TABLE_NAME, BUCKET_NAME

memecam-upload-url

lambdas/get_upload_url

BUCKET_NAME

memecam-track-event

lambdas/track_event

TABLE_NAME

memecam-get-stats

lambdas/get_stats

TABLE_NAME

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

GET

/memes

memecam-list-memes

POST

/memes/upload-url

memecam-upload-url

POST

/events

memecam-track-event

GET

/stats

memecam-get-stats

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 ejemplo https://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.zip

9.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.

MemeCam · Congreso CIETA XVIII

Read post →

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