discourse-to-markdown es un nuevo plugin que devuelve el contenido del foro en formato Markdown cuando el cliente envía Accept: text/markdown o añade .md al final de cualquier URL de contenido.
Lo estamos ejecutando en nuestro propio foro en https://discourse.roots.io:
curl -H "Accept: text/markdown" https://discourse.roots.io/latest
curl https://discourse.roots.io/t/serve-your-wordpress-posts-as-markdown/30321.md
El HTML es costoso de alimentar a un LLM, y servir Markdown que solo contiene el contenido suele reducir el uso de tokens entre 3 y 5 veces. Esto significa llamadas a la API más económicas, respuestas más rápidas y más margen en la ventana de contexto para que el modelo razone. Consulta https://acceptmarkdown.com para una presentación más detallada y una verificación de compatibilidad para cualquier sitio.
Cómo los clientes solicitan Markdown
Tres puntos de entrada:
- Cabecera
Accept: text/markdown(ideal para LLMs) - Sufijo de URL
.md - Detección (cada respuesta HTML anuncia su hermano Markdown mediante
Link: <...>; rel="alternate"; type="text/markdown"y una etiqueta<link rel="alternate">en<head>, los feeds RSS incluyen un<atom:link>que apunta a la equivalente en Markdown)
Rutas compatibles
| Ruta | HTML | Markdown |
|---|---|---|
| Tema | /t/:slug/:id |
/t/:slug/:id.md |
| Publicación única | /t/:slug/:id/:post_number |
/t/:slug/:id/:post_number.md |
| Categoría | /c/:slug/:id |
/c/:slug/:id.md |
| Etiqueta | /tag/:tag |
/tag/:tag.md |
| Último | /latest |
/latest.md |
| Top | /top |
/top.md |
| Popular | /hot |
/hot.md |
| Actividad de usuario | /u/:username/activity |
/u/:username/activity.md |
Instalación
Añade el plugin a tu app.yml:
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/roots/discourse-to-markdown.git
Reconstruye el contenedor:
cd /var/discourse
./launcher rebuild app
Luego actívalo en Admin → Configuración → Plugins → Salida Markdown.
Notas sobre la conversión
El plugin convierte el HTML cooked de Discourse —la representación renderizada que ven los lectores, con oneboxes expandidos, menciones enlazadas y citas atribuidas—, no el raw. Esto preserva lo que realmente ven los lectores y mantiene la salida portable en cualquier renderizador compatible con GFM. Las construcciones específicas de Discourse (citas, oneboxes, detalles, menciones, hashtags, emojis, lightboxes, encuestas) se reescriben de manera lógica antes de la conversión.
El Markdown convertido se almacena en caché en Redis por publicación, usando como clave post.id + post.updated_at, y las ediciones invalidan automáticamente la caché.
Configuración
| Configuración | Valor predeterminado | Propósito |
|---|---|---|
discourse_to_markdown_enabled |
false |
Interruptor principal del plugin |
discourse_to_markdown_md_urls_enabled |
true |
Aceptar sufijos de URL .md como hermanos de la ruta HTML |
discourse_to_markdown_strict_accept |
false |
Devolver 406 Not Acceptable cuando la cabecera Accept del cliente excluye tanto text/html como text/markdown |
discourse_to_markdown_emit_vary |
true |
Emitir Vary: Accept en respuestas Markdown y 406 para que las cachés no sirvan representaciones cruzadas |
discourse_to_markdown_include_post_metadata |
true |
Incluir URL, categoría, etiquetas, autor y marcas de tiempo en la representación Markdown |
Recursos
- Código/problemas: GitHub - roots/discourse-to-markdown: Serve Discourse content as Markdown via Accept: text/markdown or .md URLs — content negotiation for LLMs and agents. · GitHub
- acceptmarkdown.com — servir Markdown a agentes mediante negociación de contenido, más una verificación de compatibilidad para tu sitio
- RFC 9110 §12.5.1 — Negociación proactiva — la especificación que implementa este plugin
- RFC 7763 — registro del tipo de medio
text/markdown - MDN — Negociación de contenido — introducción accesible al concepto
- Consulta acceptmarkdown.com/reference para la especificación completa y la lista de documentación para desarrolladores