🚀 Migrando mi Obsidian Vault a un sitio web estático con Quartz 4, GitHub Pages y automatización total
En este artículo cuento el proceso completo que seguí para transformar mi vault de Obsidian en un sitio web estático moderno usando Quartz 4, desplegarlo en GitHub Pages, automatizar la subida con scripts, e integrar sincronización directa con Obsidian gracias al plugin Quartz Syncer.
Fue un camino lleno de decisiones, ajustes técnicos y descubrimientos útiles, así que aquí dejo todos los pasos documentados.
Ojalá le sirva a otros que quieran hacer algo similar.
🗂️ 1. Preparando el entorno
Mi objetivo era claro:
“Quiero publicar parte de mi Obsidian Vault como un sitio web, con control de versiones en GitHub, despliegue automático y un theme personalizado.”
Para esto usé:
- MacBook Pro
- Obsidian + mi theme personalizado
- Quartz 4 (nuevo framework, no basado en Hugo)
- GitHub Pages
- (Opcional) Un servidor VPS con Plesk ( no llegué a usarlo, me animé por GitHub Pages)
📦 2. Instalando Quartz 4 en mi Mac
Quartz no se instala como un paquete global. Simplemente clonas la plantilla y trabajas dentro:
git clone https://github.com/jackyzha0/quartz.git mi-quartz
cd mi-quartz
npm installPara ver el sitio localmente:
npx quartz build --serveQuartz corre en http://localhost:8080.
🔗 3. Conectando Quartz con mi Obsidian Vault
Tenía mi vault en:
/Users/…/Nextcloud/obsidian-MHO2212
Y quería que Quartz usara la subcarpeta Public/ como contenido del sitio.
En Quartz, la carpeta que actúa como contenedor de notas es siempre:
mi-quartz/content
Probamos dos opciones:
✔️ A. Enlace simbólico (funcionó al inicio)
ln -s /Users/.../obsidian-MHO2212/Public contentPero esto luego lo reemplazamos con Quartz Syncer, más adelante en el proceso.
🧹 4. Limpieza masiva del frontmatter
Muchas de mis notas tenían errores YAML como:
tags: []
- mocsPara limpiarlo, generamos un script Python que removió todas las líneas problemáticas:
import os
from pathlib import Path
# 👉 CAMBIA ESTA RUTA POR LA DE TU VAULT
VAULT_PATH = Path("AQUI LA RUTA")
def fix_file(path: Path):
text = path.read_text(encoding="utf-8")
# Solo nos interesa si tiene frontmatter YAML
if not text.startswith("---"):
return False
lines = text.splitlines(keepends=True)
# Localizar bloque de frontmatter (entre los dos primeros '---')
fm_start = 0
try:
fm_end = next(
i for i in range(1, len(lines))
if lines[i].strip() == "---"
)
except StopIteration:
return False # frontmatter mal formado, mejor no tocar
frontmatter = lines[fm_start:fm_end+1]
# Comprobar si tiene tags: [mocs]
has_inline_mocs = any("tags:" in l and "[mocs]" in l for l in frontmatter)
if not has_inline_mocs:
return False
# Borrar líneas tipo " - mocs" dentro del frontmatter
new_frontmatter = []
changed = False
for l in frontmatter:
stripped = l.strip()
if stripped == "- mocs":
changed = True
continue # saltamos esta línea
new_frontmatter.append(l)
if not changed:
return False
# Volver a montar el archivo
new_lines = new_frontmatter + lines[fm_end+1:]
new_text = "".join(new_lines)
# Hacer copia de seguridad
backup_path = path.with_suffix(path.suffix + ".bak")
backup_path.write_text(text, encoding="utf-8")
# Escribir el archivo corregido
path.write_text(new_text, encoding="utf-8")
return True
def main():
count = 0
for root, dirs, files in os.walk(VAULT_PATH):
for name in files:
if not name.endswith(".md"):
continue
p = Path(root) / name
if fix_file(p):
count += 1
print(f"Arreglado: {p}")
print(f"\nTotal de archivos modificados: {count}")
if __name__ == "__main__":
main()
Esto resolvió la mayor parte de los errores, pero no permitió que se indexen en Quartz todo el vault (tampoco era lo que se quería)
🔧 5. Configurando Quartz 4 (quartz.config.ts)
Activé funciones avanzadas, incluyendo soporte para HTML embebido:
Plugin.ObsidianFlavoredMarkdown({
enableInHtmlEmbed: true,
}),Esto permite usar directamente:
<iframe src="..."></iframe>Aunque descubrimos que Brave y algunos bloqueadores impiden que los iframes de LinkedIn carguen correctamente, pero esto es por la seguridad de los navegadores no de Quartz, la solución que halle fue permitir los iframe.

📤 6. Subiendo el sitio a GitHub
Inicializamos el repo real:
git init
git remote add origin https://github.com/marchelo2212/mi-quartz.git
git checkout -b v4
git add .
git commit -m "Inicializando Quartz"
git push -u origin v4🚨 Importante:
GitHub ya no acepta contraseñas → usar Tokens (PAT).
🌐 7. Configurar GitHub Pages con Quartz
Usé el dominio:
https://marchelo2212.github.io
Configuración final del workflow (.github/workflows/deploy.yml):
on:
push:
branches:
- v4
permissions:
contents: write
pages: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm install
- run: npx quartz build
- uses: actions/upload-pages-artifact@v3
with:
path: public
deploy:
needs: build
permissions:
pages: write
id-token: write
uses: actions/deploy-pages@v4Cuando todo está bien, el sitio se despliega automáticamente cada vez que hago:
git add .
git commit -m "update"
git push🤖 8. Automatizando con un script deploy.sh
Creamos un script que:
- cambia a la rama correcta
- hace pull
- hace build
- hace commit si hay cambios
- sube a GitHub
#!/usr/bin/env bash
set -e
# RUTAS
QUARTZ_REPO="Ruta-repo-PC/mi-quartz"
PAGES_REPO="Ruta-repo-github-pages/marchelo2212.github.io"
echo "🧭 Cambiando a repo Quartz..."
cd "$QUARTZ_REPO"
echo "🌿 Cambiando a rama v4..."
git checkout v4 # Mi main es V4
echo "🔍 Revisando cambios locales en Quartz..."
if [ -n "$(git status --porcelain)" ]; then
echo "📌 Hay cambios locales en Quartz. Haciendo commit..."
git add .
git commit -m "Cambios locales en Quartz antes de deploy"
else
echo "✅ No hay cambios locales en Quartz."
fi
echo "⬇️ Haciendo pull de los cambios que envió Quartz Syncer..."
git pull --rebase origin v4
echo "🧱 Generando sitio con Quartz..."
npx quartz build
echo "📦 Copiando resultado al repo de GitHub Pages..."
rm -rf "$PAGES_REPO"/*
cp -R public/* "$PAGES_REPO"/
echo "📤 Haciendo commit y push en marchelo2212.github.io..."
cd "$PAGES_REPO"
git add .
git commit -m "Deploy automático desde deploy.sh" || echo "ℹ️ No hay cambios nuevos para commitear en Pages."
git push
echo "✅ Deploy completado. Revisa https://marchelo2212.github.io"🔁 9. Integración nativa con Obsidian: Quartz Syncer
En vez de usar enlaces simbólicos (primera opción que tomé), instalé el plugin:
👉 https://saberzero1.github.io/quartz-syncer-docs/
Este plugin permite:
- elegir qué carpeta del vault se publica
- sincronizar cambios automáticamente a GitHub
- manejar frontmatter automáticamente
- publicar/despublicar notas desde Obsidian
En mi caso configuré:
- Repo:
mi-quartz - Branch:
v4(Esto no está textual pero toma el repo main, por ello puse v4 como main) - Token:
PAT con contents:write - Carpeta raíz:
Public/
Esto reemplazó totalmente el enlace simbólico.
🎨 10. Personalización del theme
Quartz permite extender los componentes del layout editando:
quartz.layout.ts
quartz/styles/custom.scss
Agregué:
- botones para ocultar/mostrar sidebars
- ajustes de flex
- colores adaptados a mi theme de Obsidian
Ejemplo:
Component.Flex({
components: [
{ Component: Component.Search(), grow: true },
{ Component: Component.Darkmode() },
{ Component: Component.ReaderMode() },
]
})Pueden ver los resultados en https://marchelo2212.github.io Aquí el repo de mi quartz, donde podrán ver las modificaciones hechas en él: GitHub - marchelo2212/mi-quartz: mi-quartz
✔️ 11. Resultado final
Ahora tengo un flujo así:
- Escribo notas en Obsidian → dentro de
Public/ - Quartz Syncer detecta cambios → los envía al repo en
v4(main) - Ejecuto mi
deploy.sh. para llevar de quartz a mi sitio web- GitHub Actions construye Quartz
- GitHub Pages actualiza el sitio
- El sitio queda publicado en:
👉 https://marchelo2212.github.io Todo sin tocar terminal si no quiero.
Y si quiero ajustes técnicos, puedo usardeploy.sh.
📌 Conclusiones y aprendizajes
- Quartz 4 es muy flexible, pero requiere entender su estructura.
- GitHub Pages + Actions da un flujo perfecto para sitios estáticos.
- Obsidian + Quartz Syncer convierte tu vault en un CMS real.
- Los bloqueadores como Brave afectan mucho los embeds.
- Personalizar Quartz es tan simple como editar TS/SCSS.