Pipeline Node.js para publicar en Medium, Substack y Dev.to
En pocas palabras: El desarrollador zaerohell mostró en Dev.to, el 6 de octubre de 2026, un pipeline en Node.js: un script lee src/article.md, agrega front-matter con gray-matter, normaliza \r\n y genera cuatro archivos (Medium y Substack, en inglés y español), registrados en metadata.json. Genera archivos; no publica.
Un desarrollador publicó el 6 de octubre de 2026 en Dev.to un pipeline en Node.js para automatizar publicación de artículos: toma un markdown fuente, le agrega front-matter con gray-matter, normaliza los saltos de línea y marca flags en un metadata.json. Genera archivos, no publica.
Un pipeline de contenido automatizado es un conjunto de scripts que toma un texto fuente único y lo convierte en la versión que necesita cada plataforma de publicación (formato, metadatos, idioma), registrando qué ya se produjo. El caso del autor zaerohell usa Node.js, la librería gray-matter para el front-matter YAML y un archivo JSON como manifiesto de estado. Sirve a quien publica el mismo texto en varios lugares.
En este artículo:
- En 30 segundos
- ¿Por qué falla copiar y pegar un artículo en Medium, Substack y Dev.to?
- ¿Por qué no alcanza con un script Bash con sed?
- ¿Cómo automatizar la publicación de artículos con Node.js, paso a paso?
- ¿Para qué sirve el metadata.json y cómo evita duplicados?
- ¿Qué límites tiene este enfoque antes de usarlo en producción?
- ¿Qué está confirmado y qué no?
- Errores comunes al armar un pipeline así
- Preguntas Frecuentes
- Conclusión
- Fuentes
En 30 segundos
- Un solo archivo, src/article.md, alimenta cuatro salidas: medium_en, medium_es, substack_en y substack_es.
- El autor atribuye el error 422 de la API de Dev.to a retornos de carro (\r) en el cuerpo del artículo.
- El script escribe archivos y marca flags en metadata.json, pero no llama a ninguna API de publicación.
- Según el README oficial de Medium, consultado el 2026-10-06, su API ya no tiene soporte y no acepta integraciones nuevas.
- La API de Forem (Dev.to) tiene POST /api/articles con api-key, y published viene en false por defecto.
¿Por qué falla copiar y pegar un artículo en Medium, Substack y Dev.to?
Falla porque cada plataforma es sensible a un detalle distinto del archivo, y a mano siempre se te escapa uno. Según el relato del autor en su post de Build in Public, los saltos de línea perdidos rompían el HTML en Medium, Substack rechazaba el archivo sin front-matter y la API de Dev.to devolvía 422 Unprocessable Entity cuando el cuerpo traía retornos de carro.
Los síntomas llegaban a ClickUp como avisos: “Medium draft not generated”, “Substack draft missing” y “Dev.to build failed”.
Eso sí: es la experiencia de una sola persona, no un estudio. Te sirve como mapa de fallas probables, no como estadística. Sobre eso hablamos en desplegar automáticamente con GitHub Actions.
¿Por qué no alcanza con un script Bash con sed?

Porque sed reemplaza texto y nada más. El primer intento del autor funcionó con el placeholder {date}, pero se cayó por tres motivos concretos.
- Rutas con fecha fija. El 2026/10/04 estaba escrito a mano, así que el script se rompía al día siguiente.
- Terminaciones de línea. sed dejó \r\n en la salida y Dev.to rechazó el payload.
- Sin estado. No había forma de saber qué plataformas ya estaban generadas, y eso producía PRs duplicados.
¿Cómo automatizar la publicación de artículos con Node.js, paso a paso?
El autor usa un script, scripts/generate.js, que lee un solo markdown (src/article.md) y escribe cuatro archivos en content/2026/10/04/content-automation/, junto a un metadata.json. Cada archivo sale con su propio front-matter y con saltos de línea estilo Unix.
- Leer el manifiesto y la fuente. El script carga metadata.json y src/article.md.
- Armar el front-matter por plataforma. Con gray-matter, title para Medium y subject para Substack.
- Normalizar. Un replace(/\r\n/g, ‘\n’) saca los retornos de carro.
- Escribir y marcar. Guarda el archivo y pone en true el flag de esa plataforma e idioma.
Este es el núcleo, abreviado del post:
const matter = require('gray-matter');
// ...
const { content } = matter.stringify(raw, frontMatter);
const normalized = content.replace(/\r\n/g, '\n');
fs.writeFileSync(outPath, normalized, 'utf8');
manifest.generated[`${platform}_${lang}`] = true;gray-matter es una librería de Node.js que separa el front-matter (YAML por defecto) del contenido y devuelve un objeto con data y content. Según el README de gray-matter, su método stringify hace el camino inverso: recibe el texto y un objeto de datos, y devuelve un String con el YAML entre delimitadores — seguido del contenido.
Lo lindo del esquema es que lo corrés, mirás que se hayan escrito los cuatro archivos, revisás el diff, mandás el PR, y la próxima vez que lo ejecutes el script saltea lo que ya está hecho, sin que tengas que acordarte de qué plataforma te faltaba. Para sumar un destino agregás una entrada al array platforms.
¿Para qué sirve el metadata.json y cómo evita duplicados?
Es el manifiesto que dice qué archivos ya se generaron. Tiene los campos repo, date, languages, topics, commits (3 en el ejemplo del post), pull_requests, releases, closed_issues y un objeto generated con un flag booleano por plataforma e idioma, cuatro en total. Relacionado: workflows con IA en GitHub.
El script escribe solo los archivos cuyo flag está en false y guarda el manifiesto al final, por eso volver a correrlo no regenera lo hecho. Ojo con el significado: generated quiere decir archivo escrito, no artículo publicado.
Una inferencia mía sobre el código: como el manifiesto se persiste recién al final, si el script se corta a mitad de camino los flags no se guardan y la próxima corrida vuelve a escribir esos archivos.
¿Qué límites tiene este enfoque antes de usarlo en producción?
El pipeline genera archivos y no publica: el código no llama a ninguna API, aunque el post hable de un paso de publicación “zero-touch”. Antes de llevarlo a producción hay cinco puntos para revisar.
- No publica nada. Después de correrlo, alguien tiene que subir cada archivo.
- Dev.to no está en el código. Aparece en el resumen (TL;DR) y en la sección del problema, pero ni el array platforms ni el manifiesto tienen una entrada para esa plataforma.
- La ruta sigue fija. El código final apunta a content/2026/10/04/…, el mismo defecto que se le criticaba a sed.
- La desestructuración parece incorrecta. Según la documentación, stringify devuelve un string, y el script hace const { content } = matter.stringify(…). Si es así, content queda en undefined y el replace tira un error. Probalo antes de copiarlo; con
const out = matter.stringify(raw, frontMatter)y normalizando out debería andar (propuesta mía, sin probar). - El front-matter del post se ve raro. Los títulos vienen con el campo tags metido dentro del string. Puede ser un error de copia, pero revisalo.
¿Qué pasa con la API de Medium?
Según el README del repositorio oficial, consultado el 2026-10-06, la advertencia dice, en inglés, “The Medium API is no longer supported” (la API de Medium ya no tiene soporte), y aclara que no se aceptan integraciones nuevas. Según el README de medium-api-docs, los tokens de integración propios no vencen y el usuario puede revocarlos cuando quiera; el login por navegador quedó solo para integraciones existentes. El estado de soporte puede cambiar, así que revisá el README de nuevo antes de decidir.
Mi lectura: si arrancás hoy, tratá a Medium como un destino de copia asistida y no apuestes tu flujo a esa API. Cubrimos ese tema en detalle en automatizar flujos con n8n sin código.
¿Qué sí se puede automatizar en Dev.to?
Con la API de Forem, que usa Dev.to, mandás un POST a https://dev.to/api/articles con el header api-key y un JSON con title, body_markdown, published (false por defecto, o sea borrador), tags (hasta 4, separados por coma), series y canonical_url. Lo dice la documentación oficial de Forem API V1, que además indica que body_markdown acepta YAML front matter al inicio, así que la salida de gray-matter encaja en principio.
Mi propuesta editorial: si republicás el mismo texto, cargá canonical_url con la URL original y arrancá con published en false para revisar el borrador.
¿Qué está confirmado y qué no?
Confirmado en las fuentes:
- El autor describe tres fallas y un primer intento con sed que abandonó.
- La estructura de carpetas y el manifiesto con cuatro flags figuran en el post.
- matter.stringify devuelve un String, según el README de gray-matter.
- La API de Medium figura sin soporte en su README oficial (consultado el 2026-10-06), y Forem tiene POST /api/articles.
Sin confirmar:
- Que el script funcione tal cual está en el post (no lo ejecutamos).
- Que Medium siga aceptando publicaciones por API hoy, incluso con tokens viejos.
- Que Substack rechace archivos sin front-matter: lo afirma el autor y las fuentes no lo documentan.
- Que los \r sueltos causen el 422: es el diagnóstico del autor y la documentación de Forem consultada no lo detalla.
Criterio práctico de verificación (propuesta editorial, no viene del autor ni lo probamos nosotros): guardá un article.md de prueba con terminaciones CRLF, corré el script en una carpeta vacía y buscá \r en los archivos de salida con una búsqueda por regex en tu editor. Después mandá un borrador con published en false a Dev.to y fijate si lo acepta en vez de rechazarlo con 422.
Errores comunes al armar un pipeline así
- Normalizar solo \r\n. Un \r suelto no coincide con /\r\n/g. Probá /\r\n?/g (propuesta sin probar).
- Tratar generated: true como publicado. Agregá un campo aparte, por ejemplo published, para no confundir archivo escrito con artículo en línea.
- Republicar sin canonical_url. Si el mismo texto vive en tres sitios, indicá cuál es el original.
- Planear la integración sobre la API de Medium. Con la API sin soporte, diseñá ese paso como manual.
Preguntas Frecuentes
¿Cómo publicar el mismo artículo en Medium, Substack y Dev.to sin copiar y pegar?
Con un markdown fuente único y un script que genere la versión de cada plataforma, que es lo que hace el pipeline del post. Hoy ese script escribe archivos para Medium y Substack pero no publica; para Dev.to podés sumar una llamada a POST /api/articles con api-key. En Medium queda un paso manual porque, según su README consultado el 2026-10-06, no acepta integraciones nuevas.
¿Para qué sirve gray-matter en Node.js?
gray-matter separa el front-matter (YAML por defecto) del contenido de un texto y devuelve un objeto con data y content. Con matter.stringify hacés lo inverso: devuelve un string con el front-matter adelante. En este pipeline agrega title o subject a cada archivo. Te puede servir nuestra cobertura de rellenar PDFs automáticamente en n8n.
¿Por qué la API de Dev.to devuelve 422 Unprocessable Entity?
Según el autor del post, la API devolvía 422 cuando el cuerpo del artículo traía retornos de carro (\r). La documentación de Forem que revisamos no detalla esa causa, así que tomalo como el diagnóstico de una persona. Normalizá el texto antes de enviarlo y, si sigue fallando, leé el cuerpo de la respuesta de error.
¿Cómo convertir saltos de línea \r\n a \n en Node.js?
Usá texto.replace(/\r\n/g, ‘\n’), la línea que emplea el autor. Si tus archivos pueden traer un \r suelto, replace(/\r\n?/g, ‘\n’) también lo cubre (propuesta nuestra, sin probar).
¿La API de Medium todavía permite publicar artículos?
Está sin soporte: según el README oficial de Medium, consultado el 2026-10-06, la API ya no tiene soporte y no se aceptan integraciones nuevas. Las existentes pueden seguir con tokens de integración, pero el README no garantiza que funcionen, así que probalo con tu propio token antes de depender de eso. Como el estado de soporte puede cambiar, volvé a revisar el README antes de armar tu flujo.
Conclusión
El pipeline del post resuelve bien la parte de generar versiones consistentes desde un solo markdown, y el manifiesto con flags es una idea reutilizable. Lo que todavía no resuelve es publicar, ni incluye a Dev.to, y el código tiene al menos una línea que conviene probar antes de copiar.
Mi recomendación: tomá la estructura (fuente única, front-matter por plataforma, manifiesto idempotente), corregí la fecha fija y la desestructuración, y sumá Dev.to con la API de Forem usando published en false y canonical_url. Para Medium, dejá un paso manual.
Fuentes
- Automating Multi-Platform Article Publishing with a Node.js Content Pipeline – post original del autor en Dev.to (6 de octubre de 2026)
- Medium API docs – README oficial con la advertencia de que la API ya no tiene soporte (consultado el 2026-10-06)
- Forem API V1 – documentación oficial del endpoint para publicar artículos
- gray-matter – README oficial del parser de front-matter para Node.js






