Este blog iba a ser un CMS. Tenía la cuenta de Sanity abierta, el esquema medio dibujado y la excusa perfecta: "así aprendo la herramienta". Lo cerré y lo hice con archivos Markdown dentro del repo. Este primer post explica esa decisión y las que vinieron detrás, incluyendo lo que decidí no construir.
Por qué /blog y no un subdominio#
La primera idea fue blog.davidquinta.tech. John Mueller, de Google, ha dicho que en general los tratan igual, aunque él personalmente prefiere mantener todo junto. Del lado SEO hay casos publicados donde mover un blog a una subcarpeta subió el tráfico orgánico, pero son casos de agencias, no experimentos controlados. No necesité desempatar esa discusión.
Mi razón es práctica: con /blog es el mismo proyecto, el mismo deploy y el mismo diseño que mi portafolio. Un repo, un pipeline, cero DNS extra.
MDX en el repo, no un CMS#
Sanity es muy bueno. Pero para una persona que escribe desde su editor resolvía problemas que todavía no tengo, y ponía un servicio externo entre yo y publicar. Así que cada post es un archivo MDX: Markdown que además acepta componentes de React cuando hacen falta.
export const meta = {
title: 'Cómo está hecho este blog',
description: 'Next.js con export estático, posts en MDX dentro del repo…',
date: '2026-09-12',
tags: ['Next.js', 'MDX', 'SEO'],
translation: 'how-this-blog-is-built',
}
Este blog iba a ser un CMS...La comparación que me hizo decidir:
| Aspecto | MDX en el repo | Sanity |
|---|---|---|
| Dónde escribo | VS Code | Editor web, desde cualquier lado |
| Publicar | git push | Un botón, más un webhook que reconstruye el sitio |
| Historial | Git | El del CMS |
| Servicios externos | Ninguno | Uno (Sanity) |
| Costo mensual | $0 | $0 en el plan gratis (hasta 20 usuarios); $15 por usuario al mes en el plan Growth |
| Si mañana escribe alguien más | Necesita Git y un pull request | Le creo un usuario y listo |
La última fila es la única que me hizo dudar. Hoy escribo solo. Si eso cambia, mover archivos Markdown a un CMS es trabajo de una tarde; el camino inverso es bastante más largo.
Todo sale estático#
El sitio es Next.js con output: 'export', así que next build genera HTML plano y no hay servidor. Los números: el HTML de este post pesa 9 KB comprimido con Brotli (12 KB con gzip), el build completo tarda unos 12 segundos en mi máquina, sin caché, y el proyecto tiene 10 dependencias directas (188 contando las transitivas, sin las de desarrollo).
El detalle del que más contento estoy es cómo funcionan los dos idiomas. No hay un sistema de traducciones: un post vive en content/blog/en o en content/blog/es, y si existe una versión en el otro idioma, las dos páginas se enlazan solas y le dicen a Google con hreflang que son el mismo post:
export async function getPost(lang: Lang, slug: string): Promise<Post> {
const meta = await readMeta(lang, slug)
const other = otherLang(lang)
// A translation is the same slug in the other language's folder — or
// whatever `meta.translation` points at when the two slugs differ.
const otherSlug = meta.translation ?? slug
const translated = existsSync(file(other, otherSlug)) && published(await readMeta(other, otherSlug))
const source = readFileSync(file(lang, slug), 'utf8')
return { ...meta, lang, slug, minutes: readingMinutes(source), translationSlug: translated ? otherSlug : null }
}Lo que viene incluido, y por qué
- Feed RSS por idioma, porque es la única forma de suscribirse que no depende de una plataforma.
- Una imagen para compartir por post, generada en el build con el título, porque un link sin imagen pasa desapercibido en LinkedIn.
- Datos estructurados (
BlogPosting) y un sitemap con las dos versiones de cada post, para que los buscadores entiendan qué es cada URL. - Borradores: con
draft: trueun post se ve en local y no se publica, para poder dejar cosas a medias sin miedo.
Lo que dejé fuera a propósito#
- Comentarios. Moderar spam en un blog nuevo es trabajo sin retorno. Si quieres discutir algo, escríbeme o responde donde lo compartí.
- Analytics. No quiero decidir sobre qué escribir mirando gráficas de tráfico. Si algún día lo agrego, será algo sin cookies.
- Buscador. Con menos de veinte posts, el índice es el buscador.
- Newsletter. Es un compromiso de constancia que todavía no me he ganado. Para eso está el RSS.
- Un CMS. Ver arriba.
Todo esto se puede agregar después. Nada de esto me ayuda a escribir el segundo post.
Lo que importa#
Lo que da visibilidad no es la herramienta. Es escribir seguido y que cada post tenga una URL que valga la pena compartir.
Esa es la única métrica por ahora. El compromiso: un post cada dos semanas. Y no solo de trabajo: también de cómo uso la IA para cosas que no son código, como entender mejor a mis dos pastores alemanes o prepararme para el bebé que viene en camino.
Si hay un tema que quieras que cubra, escríbeme. Y si prefieres que los posts te lleguen solos, está el feed RSS.