Proyecto personal desplegadoTypeScriptEste sitio · mangel14.dev

mangel14.dev y Content Engine

Publicar con constancia sobre lo que construyo sin que un modelo invente datos en mi nombre, con un portafolio que buscadores y asistentes de IA puedan leer y citar.

Qué hace: Convierte las notas, documentos y enlaces que le envío por Telegram en artículos del blog y posts de LinkedIn. Ninguna cifra sale sin su fuente y nada se publica sin mi confirmación.

Resumen

El sitio que estás leyendo: Next.js 16 con generación estática, en español e inglés, con datos estructurados, llms.txt y sitemap con alternativas por idioma.

En el mismo deploy de Vercel vive el Content Engine, un grafo en LangGraph.js. Recibe por Telegram lo que le mando, propone el enfoque, redacta el artículo y el post, los revisa contra un linter de estilo y espera mi aprobación de una versión exacta antes de publicar.

La necesidad

Quería publicar con constancia sobre lo que construyo, pero un modelo de lenguaje que redacta solo inventa cifras, experiencias y fuentes, y lo que se publica lleva mi nombre. El portafolio, además, tenía que poder leerlo y citarlo un buscador o un asistente de IA, no solo una persona.

Restricciones

  • Sin servidores aparte ni costo fijo: plan Hobby de Vercel, con funciones de 300 segundos como máximo y un cron al día.
  • Lo que llega por Telegram (documentos, páginas, mensajes reenviados) puede traer instrucciones escondidas: es material no confiable.
  • LinkedIn no tiene clave de idempotencia, y su formato de texto corta el post sin avisar si hay caracteres reservados sin escapar.

La solución

Un agente que trabaja como editor: extrae lo que le envío, marca qué cifras tienen fuente y cuáles no, me pregunta lo que falta, redacta en los dos idiomas con portada y diagramas, y publica solo la versión que apruebo, primero en el blog y después en LinkedIn.

Cómo funciona

El sitio es estático (SSG) con Next.js 16 y next-intl. El agente corre en las rutas API del mismo deploy de Vercel, con el estado en Postgres; no hay servidores aparte.

Flujo de datos
  1. Telegram → webhook /api/telegram: verifica el secreto, acepta solo el chat privado del autor y descarta updates repetidos
  2. Extracción: notas, Markdown, PDF (unpdf), imágenes y enlaces; cada fuente se marca como del autor o externa, y las URLs pasan por un fetch que bloquea redes privadas
  3. Investigación: afirmaciones con la fuente que las respalda; una cifra externa sin respaldo queda marcada
  4. Propuesta en Telegram: temas, tipo de artículo, datos que faltan y qué hacer con las cifras sin fuente; el autor responde en lenguaje natural
  5. Redacción, edición contra el linter, versión en inglés, portada y diagramas en SVG; cada borrador recibe una versión y un hash
  6. Publicación confirmada para esa versión exacta: commit del MDX en GitHub → deploy en Vercel → revisión de la página publicada → LinkedIn Posts API → IndexNow

Decisiones técnicas

  • Sin confirmación del autor no se publica nada, y la confirmación vale para una versión exacta: un botón de una versión anterior no publica la editada.
  • Blog y LinkedIn se aprueban por separado; si uno falla, la pieza queda «publicada en parte» y el bot dice qué falta, en lugar de anunciar un éxito que no ocurrió.
  • Todo documento, página o mensaje reenviado se trata como dato citado, nunca como instrucción para el agente.
  • Las imágenes se generan con código (SVG y next/og) con la identidad del sitio; si un texto no cabe, el agente lo dice en vez de recortarlo.
  • El agente vive dentro del deploy de Vercel con estado en Postgres, en lugar de un servidor aparte con n8n: menos piezas y sin costo fijo.

Cómo se valida

  • pnpm test: pruebas de node:test del grafo completo con un LLM simulado, de la conversación en Telegram, de seguridad (SSRF, MDX, archivos, secretos), de los visuales y de la integridad del contenido en los dos idiomas.
  • pnpm test:e2e: Playwright recorre las rutas principales en siete anchos de pantalla y revisa el desbordamiento horizontal, el menú móvil, el cambio de idioma y el 404.

Límites y próximos pasos

  • Las variables del agente están configuradas en producción (el webhook rechaza peticiones sin secreto en vez de responder «sin configurar»), pero todavía no ha publicado contenido real.
  • El primer artículo del blog sigue en borrador.
  • La publicación en LinkedIn está implementada con la Posts API pero no se ha probado contra la cuenta real; LinkedIn no tiene clave de idempotencia, así que un intento cortado a la mitad pide confirmación antes de repetirse.

Mi parte

Proyecto personal: diseño, código, contenido y despliegue.

¿Te interesa este tipo de trabajo?

Busco trabajo remoto como Full Stack Engineer. Si quieres hablar de este proyecto o de tu equipo, escríbeme.

Otros proyectos