Gabriel Herencia

~/insights / Automatización

Portadas generadas por agentes: Nano Banana 2, Cloud Storage y un Worker

El MCP de mi web ahora genera sus propias portadas: Nano Banana 2 crea la imagen, sharp la deja 85% más liviana, Cloud Storage la guarda y un Worker de Cloudflare la sirve como CDN. Todo desde el chat, a ~$0.07 por portada.

·2 min de lectura
AutomatizaciónIAMCPserverlessvercelgeminicloudflare
Portada: Portadas generadas por agentes: Nano Banana 2, Cloud Storage y un Worker

En el insight anterior conté que mi-web-es-su-propio-mcp-publicar-desde-cualquier-agente. Cerré diciendo que el siguiente paso eran las portadas generadas automáticamente. Acá están — y el camino dejó más aprendizajes que el resultado.

El flujo completo

renderizando diagrama…

El agente escribe el prompt de la imagen con libertad total y elige el formato según destino (16:9 para la web, cuadrado o vertical para redes). La tool hace el resto y el post queda con su portada online al instante.

Lo que aprendí hoy

No hizo falta Vertex. Para usar los modelos de imagen de Gemini alcanza una API key de AI Studio: mismo modelo y mismo precio que Vertex, pero una sola variable de entorno en lugar de service accounts y SDKs. Ojo: los modelos de imagen no tienen free tier — la key necesita billing. Nano Banana 2 a 1K cuesta ~$0.07 por imagen; generar las portadas de todo este blog sale menos que un café.

Cloud Storage desde serverless es un no-problema. ¿Cómo usa una web en Vercel un bucket de GCS si no hay servidor? Una service account con permiso de escritura solo sobre ese bucket, y su key JSON en base64 dentro de una variable de entorno. Tres líneas para instanciar el cliente.

El CDN con dominio propio pedía un Worker. El CNAME clásico de GCS (c.storage.googleapis.com) es HTTP-only y exige verificar el dominio. Un Worker de Cloudflare de 20 líneas proxea el bucket por HTTPS real, cachea en el edge y me da img.gabrielherencia.com. Plan free, sobra.

Optimizar antes de subir: -85%. La imagen sale de Gemini pesando ~500 KB. Un paso de sharp (JPEG progresivo, mozjpeg, calidad 82) la deja en ~80 KB sin diferencia visible. Elegí JPEG y no WebP a propósito: la portada también es la og:image, y los scrapers de las redes sociales siguen siendo poco confiables con WebP.

Nombres versionados por contenido. Cada archivo se llama slug-{hash}.jpg y se sube con Cache-Control: immutable. Regenerar una portada produce una URL nueva: nunca hay que invalidar caché ni pelearse con el CDN.

El bonus track: sharp rompió producción. El primer deploy devolvía 500 en todo el MCP. ¿La causa? El bundler intentaba empaquetar los binarios nativos de sharp dentro de la función serverless. La solución: serverExternalPackages en la config de Next (que se resuelvan en runtime) e imports lazy, para que si una dependencia pesada falla, rompa una sola tool y no todo el servidor. Verdad de fondo aplicada: el código era correcto localmente; la evidencia (500 sin auth, resto del sitio sano) apuntaba al empaquetado, no a la lógica.

La foto completa

Publicar un insight hoy es una conversación: lo redacto con un agente, el agente lo publica, genera la portada con el estilo que le pida, y si quiero lo comparte en LinkedIn. La web dejó de ser algo que mantengo y pasó a ser algo con lo que converso.