Cómo construí mi blog con Next.js y Obsidian
Quería un blog, pero no quería un CMS. No quería aprender otra interfaz, no quería depender de una plataforma externa y tampoco quería que mi contenido viviera separado del resto de mis notas. La solución fue conectar directamente Obsidian con el blog.
Por qué Obsidian
Ya usaba Obsidian en todos mis dispositivos. Me acomoda escribir en Markdown — si llevas tiempo desarrollando apps, sabes que el formato está en todos lados: READMEs, documentación, comentarios. Escribir así se vuelve natural.
Además, tengo mi vault organizado con la metodología PARA y Zettelkasten, así que era cuestión de crear una carpeta y cualquier .md que ponga ahí se convierte en un post.
Stack tecnológico
- Next.js 16.4 con App Router y React 19
- Tailwind 4 para los estilos
- gray-matter para leer el frontmatter de los
.md - remark/rehype para convertir Markdown a HTML
- Vercel para el despliegue
Sin base de datos, sin CMS, sin nada extra. El contenido son archivos .md planos.
Lo que tiene el blog hoy
Empezó como una lista de posts y fue creciendo. Lo que tiene ahora:
- Comentarios con Giscus: cada post tiene su hilo, guardado en GitHub Discussions. Sin base de datos propia y sin otro servicio que mantener.
- Newsletter con Resend: quien quiera puede suscribirse y recibir los posts nuevos por correo.
- Búsqueda con Fuse.js: búsqueda difusa en el navegador sobre todos los posts, sin servidor de búsqueda.
- RSS por tag: además del feed general, cada tag tiene su propio feed, por si solo te interesa un tema.
- Archivo: todos los posts ordenados por fecha en una sola página.
- Vídeos: una sección con los vídeos que acompañan a algunos tutoriales.
- Portafolio de proyectos: los posts pueden asociarse a un proyecto desde el frontmatter, y cada proyecto tiene su página.
Todo sigue saliendo de los mismos archivos Markdown del vault: añadir una funcionalidad no cambió dónde ni cómo escribo.
Cómo funciona la sincronización
El vault de Obsidian vive en su propio repo privado en GitHub. El blog lo referencia como un git submodule apuntando a la carpeta que tengo para el blog dentro del vault.
El problema con los submódulos es que el puntero no se actualiza solo — cada vez que agregas un post, tendrías que entrar al repo del blog y actualizarlo manualmente. Para resolver eso, configuré un GitHub Action en el vault.
Cuando hago push al vault con un post nuevo, el Action entra al repo del blog, actualiza el submódulo al commit más reciente y hace push. Vercel detecta el cambio y redespliega automáticamente.
El flujo completo
flowchart LR
A[Obsidian<br/>escribo el post] -->|Obsidian Git| B[(Repo del vault)]
B -->|GitHub Action| C[(Repo del blog<br/>submódulo content/vault)]
C -->|push| D[Vercel<br/>build Next.js]
D --> E[Post publicado]
- Escribo un
.mden Obsidian con el frontmatter correcto - Obsidian Git hace push al vault en GitHub
- El GitHub Action detecta el push y actualiza el submódulo en el repo del blog
- Vercel detecta el nuevo commit y redespliega
Desde que termino de escribir hasta que el post aparece publicado, no tengo que tocar nada más. El contenido fluye solo.
Lo que habría hecho diferente
El submódulo funciona bien, pero tiene sus fricciones. Si empezara de cero, evaluaría usar la API de GitHub directamente desde el Action para leer los archivos del vault privado, en lugar de manejar permisos de submódulo entre repos. Más simple de mantener a largo plazo.
Si te interesa el detalle de la automatización, en este post explico el GitHub Action paso a paso. Y si quieres ver cómo organizo el contenido antes de publicarlo, escribí sobre mi sistema PKM con Zettelkasten y PARA.