Soy Ming. Además del trabajo de product design en vm0, llevar nuestro contenido también es parte de mi rol, y resultó tener mucho más detrás de lo que yo esperaba: diseño de workflows, ilustraciones, producción de imágenes, trabajo con el CMS, traducciones. Esto es lo que he ido armando para hacerlo manejable.
El contenido es una de las cosas que hago aquí
La mayoría de mi día en vm0 lo paso entre product design y nuestro repo de Next.js. Pero llevar nuestro contenido también está en mi plato, y al meterme en serio, me di cuenta de cuánto trabajo lleva un blog que de verdad funciona. Hace falta output consistente, investigación de keywords real, visuales coherentes con la marca, meta descriptions decentes, y traducciones a los cuatro idiomas que soportamos.
Cuando empecé a hacerlo en serio, cada post me llevaba casi un día entero. La escritura en sí era una rebanada pequeña de eso. La mayor parte del tiempo iba al trabajo de producción alrededor de la escritura: encontrar las keywords correctas, hacer la portada, dejar bien los campos del CMS, repetirlo todo por cada locale.
Así que poco a poco fui pasando todo lo que pude de esa pipeline a Lucas, un AI marketing agent que construí sobre Zero alrededor de mi propio trabajo del día a día. Está configurado con el rol "Marketing Manager," y su alcance es cualquier cosa relacionada con marketing: la producción del blog es la parte más armada hoy, y va creciendo a medida que sumo skills y connectors.
Por ahora Lucas tiene acceso a nuestro CMS Strapi headless, a nuestra cuenta de Ahrefs, al Slack del equipo, a nuestro web chat, a una skill interna llamada draw para ilustraciones consistentes con la marca, además de la skill estándar copywriting para la mecánica de escritura.
Abajo te cuento cómo funciona esta AI blog automation en la práctica: cómo Lucas toma un prompt vago, lo descompone en tema y keywords, escribe un post, dibuja una portada, hace pasar el texto por traducción naturalista, y aterriza cuatro drafts de locales en nuestro CMS headless. Luego cuento cómo llegué hasta acá y qué dejo deliberadamente para humanos (mayormente yo).
Cómo uso a Lucas: la web app y Slack

Con Lucas trabajo principalmente desde el web chat de vm0. Esa es la interfaz de trabajo profundo donde me siento con él a recorrer estructura, borrador, iteraciones de portada y ediciones. Threads largos, contexto largo, el tipo de ida y vuelta que sería incómodo en un canal de chat.
Lucas también está conectado a nuestro Slack de equipo, como punto de entrada compartido. Tiro prompts rápidos ahí desde el móvil, y el resto del equipo también puede pingearle. Quien esté en la rotación del blog arranca un post de la misma forma. El mismo agente, el mismo contexto entre las dos interfaces.
Cómo se ve un prompt típico
Mis prompts a Lucas son cortos. Tres frases máximo. Uno representativo:
Lucas, write a tutorial on running effective weekly meetings: cover meeting structure, common pitfalls, and how to keep remote teams engaged. Tutorial style, SEO-friendly, end with a CTA to use Zero. Draft link only, don't publish.
Ese es el brief entero. Un mensaje. Sin esquema, sin lista de keywords, sin design brief, sin objetivo de longitud. Lucas se encarga del resto.
Tardé un tiempo en aterrizar este formato. Al principio escribía briefs mucho más largos porque asumía que el agente necesitaba todo deletreado, y después me di cuenta de que casi todo el contexto pertenece a sus instrucciones permanentes y a sus skills, no a cada prompt individual. El prompt es un trigger; el peso lo lleva la configuración.
Cómo Lucas analiza el tema y las keywords

El primer movimiento de Lucas es extraer estructura del prompt. Para una petición como la de arriba, sus notas de trabajo se ven así:
- Tema: llevar reuniones semanales efectivas
- Formato: tutorial → pasos numerados, ejemplos concretos, lenguaje "haz esto"
- Audiencia implícita: team leads, managers remotos, founders
- Secciones obligatorias: estructura de la reunión, errores comunes, engagement remoto
- CTA: llevar al lector a Zero
- Restricción: solo draft URL, no publicado
Después elige la keyword. Esta es la parte del marketing de contenidos para la que menos intuición tenía cuando empecé, así que le di a Lucas una rutina para recorrer cada vez que lo pongo a trabajo de keywords. No es una skill autónoma, sino una secuencia en la que confío:
- Sacar candidatas de Ahrefs. Llama a la Ahrefs API sobre la frase del tema y obtiene variaciones long-tail con volumen mensual, keyword difficulty (KD), parent topic e intent del SERP.
- Filtrar por difficulty. Le di una regla dura: KD < 30. vm0 es un dominio relativamente nuevo con autoridad limitada, así que perseguir keywords con KD alto no tiene sentido todavía. Long-tail gana al principio.
- Cruzar contra nuestro índice de Strapi. Tira de cada slug publicado vía la REST API de Strapi y descarta cualquier keyword que ya cubramos. Sin canibalización.
- Ajustar intent al fit del producto. El intent de la keyword tiene que ser compatible con nuestra librería de casos de uso. "How to run effective weekly meetings" → operations / team management → encaja. "Best ramen in Tokyo" → no encaja, por más volumen que tenga.
- Elegir una. De la lista filtrada, elige la opción con más volumen y la usa como espina dorsal del post. Por ejemplo, remote weekly meeting best practices.
Para SEO on-page aplica una heurística simple: keyword objetivo en el título, en al menos un H2 y en las primeras 100 palabras. Sinónimos y frases relacionadas tejidas naturalmente. Enlaces internos a dos o tres posts relacionados donde encajen. Después: escribir natural, sin keyword stuffing.
El resto de la estructura (seis o siete H2s, un callout "Tip:" debajo de cada paso, un CTA al final) viene de una plantilla de tutorial que fui armando con ejemplos a lo largo de varios posts.
Cómo se dibuja la portada
La portada es la parte de la producción del blog que más me importa, en parte porque soy diseñador y en parte porque es lo que el lector ve antes de leer una sola palabra. También es la imagen Open Graph cuando los posts se comparten en X o LinkedIn, y es lo que hace que nuestro índice de blog parezca una publicación en lugar de una pared de stock photos.
Las stock photos no eran opción para el look que quería, y briefar ilustraciones una a una hubiera hecho insostenible el costo de producción por post. Así que construí una skill de Zero llamada draw. Son 200 líneas de Python que hacen cinco cosas:
- Toma dos inputs: una metáfora (qué dibujar) y un color (un nombre amigable más un ancla hex).
- Los inserta en una plantilla de prompt fija que bloquea el resto de la composición: fondo gris cálido
#eeeeee, blob de acuarela centrado en el color elegido, trazo de tinta dibujado a mano por encima, logo de vm0 en (25, 25) arriba a la izquierda. - Envía el prompt al modelo
nano-banana-prode fal.ai en 16:9. - Descarga el PNG. Normaliza los píxeles casi-blancos exactamente a
#eeeeeepara que el fondo no se vaya. Reescala a 1600×900. Compone el logo transparente vm0 con alpha encima. - Sube el resultado al CDN de archivos de vm0 e imprime la URL.
Una invocación típica se ve así:
python draw.py \
--metaphor "a tilted hourglass with sand draining into a small open notebook, a sparkle near the rim" \
--color-name "dusty rose" \
--color-hex "#e08b96" \
--upload
Dos inputs y el resto de la marca queda consistente post a post. Suelo elegir un color que pegue con el tema del post. Coral o sage para piezas tutoriales más cálidas, azul o lavanda para temas más técnicos, mostaza para anuncios. Unos pocos colores recurrentes van convirtiendo el índice del blog en una paleta reconocible.
Lo que aprendí a la fuerza es que la palanca no está en el modelo. Está en la plantilla. Si dejas al modelo elegir composición, paleta y layout libremente, cada portada parece de una marca distinta. Si lo fijas y solo le dejas elegir la metáfora, el look se mantiene coherente post a post.
Hay una skill hermana llamada illustration para spot art dentro del artículo (los dibujos más pequeños que aparecen entre las secciones de este post). Misma idea: estilo fijo, solo varían metáfora y color. Pero ajustada a arte cuadrado de 1024×1024 en vez de portadas 16:9.
Una nota corta sobre SEO de imagen: la misma portada está configurada como activo Open Graph y Twitter Card del post, así los shares sociales la levantan limpio. Strapi auto-genera cuatro variantes pre-redimensionadas en la subida (thumbnail, small, medium, large). El cuerpo del artículo todavía las carga con <img> plano en vez de vía srcset, pequeño TODO de frontend. Las ilustraciones inline llevan alt text descriptivo escrito en el markdown cuando Lucas las embebe; el alternativeText propio de la portada en Strapi es algo que todavía me queda por rellenar.
Cómo se escribe el post en sí

Cuando el tema, la keyword y la portada están fijados, redactar es bastante mecánico. Lucas:
- Hace primero un esquema. Seis o siete H2s, cada una con un trabajo claro: encuadre del problema, instrucciones paso a paso, callouts "Tip:", recap, CTA.
- Expande cada H2 a prosa con la skill
copywriting. La voz (frases cortas, ejemplos concretos, segunda persona donde aterriza, humor seco ocasional) sale de reglas que tengo en las instrucciones permanentes de Lucas, no de la skill misma. - Mete un callout "Tip:" práctico debajo de cada paso. Útil para tutoriales porque la mayoría de los lectores escanea, y los callouts les dan un camino a través de contenido largo.
- Escribe el campo
descriptiondel post. Strapi lo limita a 80 caracteres, así que se queda corto y se lee como escrito por un humano. Se usa como subtítulo del artículo y como descripción de la OG/Twitter card. - Termina con un CTA que nombra el producto y enlaza a un workspace gratis.
Un primer borrador suele llegar dos o tres minutos después del prompt. Lo leo, pido ajustes de tono donde la voz se va, y Lucas itera hasta que funciona. El primer borrador rara vez es enviable. Suele estar bastante cerca pero un poco fuera, y ahí es donde paso la mayor parte de mi tiempo de revisión.
Cómo aterriza el draft en Strapi

Usamos Strapi como CMS headless. El content type articles tiene un cover (media), author y category (relations), locale (string), y una zona dinámica blocks donde vive el cuerpo en markdown.
El flujo de sync de Lucas con el CMS:
- POST del PNG de la portada a
/api/upload. Guardar eldocumentIdque devuelve. - POST a
/api/articles?status=draftcon title, description (≤80 caracteres; Strapi lo fuerza), slug, locale, las relaciones cover/author/category como IDs numéricos, y un único bloqueshared.rich-textcon el body en markdown. - Crítico: omitir
publishedAt. Strapi trata null como estado draft. - Devolver una preview URL siguiendo el patrón de drafts de vm0:
https://www.vm0.ai/{locale}/blog/posts/{slug}?status=draft.
Aviso sobre Strapi v5: la REST API pública puede sobreescribir publishedAt para ciertos content types, lo cual significa que un "draft" creado vía API puede irse a producción en silencio. La solución es una migración de DB pequeñita que arranca ese campo en escrituras de draft.
La estrategia de slug también es relevante para SEO. Usamos un único slug canónico para los cuatro locales en lugar de traducirlo. Una lectora en /de/blog/posts/remote-weekly-meeting-best-practices ve la misma estructura de URL que una lectora en /en, y nuestro perfil de backlinks no se fragmenta entre URLs traducidas. Emitir tags hreflang link a partir de esas relaciones de locale es un TODO pequeño del frontend. Todavía no los entregamos.
Cómo funciona la traducción i18n

vm0 funciona en cuatro locales: inglés, alemán, japonés, español. No pasamos los posts por Google Translate. El camino barato destruye la voz; el camino correcto adapta los modismos.
Lucas crea primero el draft EN, captura el documentId que devuelve, y luego dispara tres llamadas PUT /api/articles/{documentId}?locale=de (y ?locale=ja, ?locale=es) con payloads traducidos de forma naturalista. Strapi los trata como variantes locale del mismo documento canónico, lo cual mantiene las cuatro versiones enlazadas en el admin y en el switcher de locale del frontend.
Reglas de traducción que le di, la mayoría salieron de toparme con outputs equivocados y corregirlos:
- No traducir términos técnicos que ya son préstamos del inglés en el idioma destino. "API," "CMS," "agent," "prompt" se quedan en inglés en JA y DE. Traducirlos suena raro en ambos idiomas.
- Adaptar modismos de forma naturalista. Una traducción literal de "kills your Friday" al alemán es un absurdo; una versión nativa de la misma metáfora aterriza.
- Re-tunear los CTAs por locale. Los imperativos se sienten más empujones en DE, así que los suavizo; la versión JA suele bajar a una invitación cortés.
- Re-tunear títulos por longitud. Los títulos en alemán suelen ser un 30% más largos que sus equivalentes en inglés. Los japoneses suelen ser más cortos. Lucas ajusta para que los títulos queden por debajo del límite de truncado de 60 caracteres en el SERP de cada locale.
Multilingual content publishing era la parte de la pipeline que más tiempo me comía. Ahora es solo el último paso de la misma corrida del agente.
Lo que no se automatiza
Una sección corta e importante. No todo en este flujo está automatizado, y es a propósito:
- Selección de tema a nivel estratégico. Lucas elige keywords dentro de un tema, pero el tema en sí viene de mí, normalmente de lanzamientos de producto, conversaciones con clientes o cambios de roadmap.
- Pasada editorial final. Leo cada draft antes de publicar. Especialmente la versión EN. El tono, la precisión técnica, las referencias a contexto interno de producto necesitan ojo humano.
- Revisión nativa para idiomas que no leo con fluidez. No leo alemán con fluidez. El draft DE va a un revisor nativo para una pasada final antes de publicar.
- Promoción. Postear en X, mandar el post a suscriptores, compartir en comunidades siguen siendo manuales por ahora.
El punto no es sacarme del loop. Es sacarme de las partes del loop que en realidad no me necesitan.
Cómo llegué a esta pipeline
No la diseñé un fin de semana. Se fue acumulando, post a post, prestando atención a qué pasos me costaban tiempo.
Lo que noté: las partes que valía la pena automatizar no eran las creativas. Eran las conectivas: los pulls de keywords, los renders de portada, las llamadas de upload, el fan-out de locales, el formateo de preview URLs. Cuando lo medí honestamente, gastaba más tiempo en logística que en la escritura misma.
Así que fui pasando la logística al agente. El modelo escribe; el agente se encarga del mover-cosas-de-un-lado-a-otro. Yo sigo siendo el que decide qué escribir y cómo debería sonar, solo que ya no soy el que cose las piezas.
Para mí, en la práctica, la automatización de contenido no terminó siendo "la IA escribe el blog". Terminó siendo "la IA hace todo lo de alrededor de la escritura, así yo tengo tiempo para de verdad mirar la escritura".
Si quieres probar algo parecido
Si estás en una situación parecida, usando más sombreros de los que querrías y con contenido como uno de ellos, la mayor parte de esto es reproducible:
- Una plataforma de agentes que te deje darle al agente un rol y skills permanentes (nosotros usamos Zero, donde vive Lucas).
- Conectores a las herramientas que ya usas: tu CMS, tu herramienta de keywords, tu generador de imágenes, tu Slack.
- Un set pequeño de skills adaptadas a tu marca (en nuestro caso
drawpara portadas ycopywritingpara tono). - Instrucciones permanentes que carguen el contexto, así los prompts pueden quedarse cortos.
Empezar un workspace gratis de Zero →
O si prefieres ver más flujos de agentes antes de registrarte, nuestra librería de casos de uso tiene 19 automatizaciones listas para copiar entre engineering, product, marketing y operations.
Si quieres clonar a Lucas en concreto: crea un agente, dale el rol Marketing Manager, conecta Strapi (o tu CMS) + Ahrefs + tu herramienta de imagen, agrega una skill draw modelada sobre la nuestra y una skill copywriting que capture tu voz de marca. El resto lo deduce a partir de tu primer prompt.


