doc-operacion — MarkUP
Última revisión: 2026-06-15 Propósito: Referencia rápida para el uso diario del sistema, resolución de problemas y mantenimiento.
1. Referencia rápida de comandos
Desarrollo
npm run dev # Servidor desarrollo → http://localhost:4321
npm run build # Build completo (astro build + pagefind)
npm run build:astro # Solo build Astro → dist/
npm run build:search # Solo indexar búsqueda (requiere dist/)
npm run preview # Previsualizar build de producción
Testing
npm test # Vitest — 6/6 tests
npm run test:watch # Vitest en modo watch (útil durante desarrollo)
Scripts auxiliares
npm run optimize-images # Convertir imágenes a WebP (usar cuando añadas imágenes nuevas)
npm run export <cat> <dir> # Exportar blog offline por categoría
npm run sync # (OBSOLETO) Usar watchexec + launchd en su lugar
2. Gestión de watchexec con launchd
watchexec es el programa que detecta cambios en src/content/ y ejecuta auto-commit.sh automáticamente. launchd es el sistema de servicios de macOS que mantiene watchexec funcionando incluso después de reiniciar el ordenador.
2.1 Verificar que el servicio launchd está corriendo
launchctl list | grep watchexec
Salida esperada (servicio activo):
PID Status Label
1234 0 com.user.watchexec
Salida esperada (servicio registrado pero no activo):
- 0 com.user.watchexec
Si no ves ninguna línea con com.user.watchexec, el servicio no está instalado. Ve a la sección 2.6 para cargarlo.
2.2 Ver logs si algo falla
# Ver errores (si hay algún problema con watchexec)
cat /tmp/watchexec.err
# Ver actividad normal (registro de cambios detectados)
cat /tmp/watchexec.log
# Ver en tiempo real (útil para depurar)
tail -f /tmp/watchexec.log
¿Qué buscar en los logs?
| Log | Qué significa |
|---|---|
Error: No such file or directory | La ruta de src/content/ no existe o es incorrecta |
Signal: SIGTERM | El proceso fue detenido (normal si reiniciaste el servicio) |
Running command... | watchexec está funcionando y ejecutó auto-commit.sh |
2.3 Reiniciar el servicio (si algo no funciona)
A veces watchexec puede quedarse en un estado inconsistente. Reiniciarlo suele resolverlo:
# Detener
launchctl stop com.user.watchexec
# Arrancar de nuevo
launchctl start com.user.watchexec
Nota: launchctl stop solo detiene el proceso temporalmente. Como el .plist tiene KeepAlive: true, launchd lo reiniciaría automáticamente. Pero si quieres forzar un reinicio inmediato, usa las dos líneas seguidas.
2.4 Detener el servicio (pausar la automatización)
Si quieres pausar la automatización (por ejemplo, durante una edición larga o mantenimiento):
# Descargar (elimina el servicio de launchd, no arrancará hasta que lo vuelvas a cargar)
launchctl unload ~/Library/LaunchAgents/com.user.watchexec.plist
Esto es útil si:
- Estás haciendo cambios masivos en
src/content/y no quieres que se hagan 50 commits individuales - Necesitas depurar algo sin que watchexec interfiera
- Vas a apagar el Mac temporalmente
2.5 Reactivar el servicio
# Cargar (vuelve a registrar el servicio en launchd, arranca inmediatamente)
launchctl load ~/Library/LaunchAgents/com.user.watchexec.plist
2.6 Instalar el servicio por primera vez (si no existe)
Si el archivo .plist no existe, créalo con el script de la guía (doc-guia, sección 3.3.1) y luego:
launchctl load ~/Library/LaunchAgents/com.user.watchexec.plist
2.7 Verificar que watchexec funciona correctamente
Para asegurarte de que watchexec + launchd están funcionando:
# 1. Verificar que el servicio está activo
launchctl list | grep watchexec
# 2. Verificar que no hay errores
cat /tmp/watchexec.err
# 3. Crear un archivo de prueba y ver si se detecta
touch /Users/ernestouriszar/markeup/src/content/test.txt
# Esperar 2-3 segundos
cat /tmp/watchexec.log # Debería mostrar "Running command..."
# 4. Limpiar el archivo de prueba
rm /Users/ernestouriszar/markeup/src/content/test.txt
3. Sincronización Android → Mac
3.1 Verificar el estado de Syncthing (Mac)
Syncthing se ejecuta como app gráfica en Mac. Para verificar:
- Buscar el icono en la barra de menú (arriba a la derecha, junto al reloj)
- Hacer clic en el icono → debería mostrar los dispositivos conectados
- Verificar la carpeta
src/content→ debe aparecer como “Up to date”
Si no ves el icono, abre Syncthing desde Finder o Launchpad.
3.2 Verificar el estado de git
cd /Users/ernestouriszar/markeup
git log --oneline -5 # Últimos 5 commits
git status # Estado actual (archivos modificados, etc.)
3.3 Force Sync manual (si hay conflictos o quieres forzar un push)
cd /Users/ernestouriszar/markeup
git pull origin main # Traer cambios remotos (por si hay conflictos)
git add src/content/ # Forzar añadir cambios locales
git commit -m "🔄 Manual sync $(date '+%Y-%m-%d %H:%M:%S')"
git push origin main
Esto fuerza un commit y push manual, lo que también dispara GitHub Actions.
4. Troubleshooting
4.1 El sitio no se actualiza después de guardar en Android
Síntoma: Guardas un post en Android pero el sitio no se actualiza después de 10 minutos.
Verificar paso a paso:
- ¿Syncthing está abierto en Mac? → Buscar icono en barra de menú. Si no está, abrir la app.
- ¿Syncthing está corriendo en Android? → Abrir la app en Android, verificar que el Mac aparece como conectado.
- ¿watchexec está corriendo? →
launchctl list | grep watchexec - ¿Se hizo el commit? →
git log --oneline -1— mirar si el último commit es reciente. - ¿GitHub Actions se ejecutó? → Ir a
https://github.com/uriszarernesto-blip/markeup/actions - ¿Cloudflare Pages desplegó? → Ir a Cloudflare Dashboard → Pages → mybrain-limpio
Solución rápida (si no hay commit):
cd /Users/ernestouriszar/markeup
git pull origin main
git push origin main
Esto fuerza un nuevo build aunque no haya cambios.
4.2 Error de build: ZodError
Síntoma: ZodError: Invalid frontmatter al ejecutar npm run build.
Causa: Un post tiene frontmatter inválido (campo faltante, tipo incorrecto, etc.).
El error te dice exactamente qué archivo y qué campo falló. Por ejemplo:
ZodError: [
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": ["title"],
"message": "Required"
}
]
Esto significa que el archivo en cuestión no tiene el campo title.
Solución:
- Localizar el post que menciona el error
- Verificar campos requeridos por
content.config.ts:title(string, obligatorio)slug(string, obligatorio)description(string, obligatorio)pubDate(date, obligatorio)categories(array de strings, mínimo 1, obligatorio)draft(boolean, opcional — default false)
- Corregir y hacer commit
4.3 Error: “must live in content collection”
Síntoma:
Collection entries must live in the "posts" collection subdirectory
Causa: Un archivo .md está en src/content/ (raíz) en lugar de src/content/posts/.
Solución:
# Mover el archivo a posts/
mv src/content/archivo-problema.md src/content/posts/archivo-problema.md
Si el problema se repite, verificar que la plantilla de Templater tenga tp.file.move() (ver doc-guia, sección 2.5).
4.4 Error de sincronización: conflicto Syncthing
Síntoma: Aparecen archivos *.sync-conflict* en src/content/.
Causa: El mismo archivo fue editado en Android y en Mac casi simultáneamente. Syncthing no sabe cuál versión es la correcta y guarda ambas.
Solución:
# 1. Listar conflictos
ls src/content/*.sync-conflict*
# 2. Revisar cuál versión es la correcta (comparar fechas o contenido)
# 3. Eliminar los conflictos
rm src/content/*.sync-conflict*
Los archivos .sync-conflict* ya están en .gitignore, pero es buena práctica limpiarlos.
4.5 El build falla en GitHub Actions
Síntoma: El workflow de GitHub Actions muestra ❌ en lugar de ✅.
Verificar:
- Ir a
https://github.com/uriszarernesto-blip/markeup/actions - Hacer clic en el workflow fallido
- Leer los logs para identificar el error
Errores comunes y soluciones:
| Error | Causa | Solución |
|---|---|---|
working-directory multiblog-obsidian does not exist | El directorio en GitHub se llama markeup, no multiblog-obsidian | Editar deploy.yml: cambiar working-directory |
ADMIN_PASSWORD not set | Secrets de GitHub no configurados | Ir a Settings → Secrets → Actions, añadir ADMIN_PASSWORD y JWT_SECRET |
npm ERR! | Dependencia corrupta o falta de espacio | Revisar logs, posiblemente un paquete necesita reinstalarse |
4.6 Error: watchexec no arranca al reiniciar Mac
Síntoma: Después de reiniciar el Mac, los cambios desde Android no se publican automáticamente.
Causa: El servicio launchd no está instalado o no está cargado.
Solución:
# 1. Verificar si el servicio existe
ls ~/Library/LaunchAgents/com.user.watchexec.plist
# 2. Si no existe, crearlo (ver doc-guia sección 3.3.1)
# 3. Cargar el servicio
launchctl load ~/Library/LaunchAgents/com.user.watchexec.plist
# 4. Verificar que está corriendo
launchctl list | grep watchexec
4.7 Error de imágenes: rutas rotas
Síntoma: Imágenes que no cargan en el sitio publicado (aparecen como 404).
Causa: La imagen referenciada en el frontmatter (image: '/img/mi-imagen.webp') no existe en public/img/.
Solución:
- Verificar que la imagen existe en
public/img/:ls public/img/mi-imagen.webp - Si la imagen está en
src/content/posts/img/(imágenes adjuntas al post), copiarla apublic/img/:cp src/content/posts/img/mi-imagen.webp public/img/mi-imagen.webp - Ejecutar
npm run optimize-imagespara optimizar las imágenes nuevas
5. Mantenimiento
5.1 Diario
- ¿watchexec (launchd) está corriendo? →
launchctl list | grep watchexec - ¿Syncthing está abierto en Mac? → Buscar icono en barra de menú
- Último commit exitoso →
git log --oneline -1 - Sin archivos conflictivos →
ls *.sync-conflict*(debe dar error “No such file”)
5.2 Semanal
-
npm run buildlocal para verificar que todo compila -
npm testpara verificar que los tests pasan - Revisar logs de GitHub Actions (últimos builds)
- Limpiar archivos temporales:
rm -f nohup.out
5.3 Mensual
-
npm outdatedpara verificar dependencias desactualizadas - Revisar Lighthouse report (si hay dominio configurado)
- Backup del repositorio (clone completo a disco externo)
- Revisar logs de watchexec:
cat /tmp/watchexec.log /tmp/watchexec.err - Verificar que el archivo
.plistde launchd sigue existiendo
6. Filosofía y decisiones de diseño
¿Por qué Syncthing en lugar de GitHub directo desde Android?
- Syncthing sincroniza archivos en tiempo real y funciona offline (red local)
- GitHub desde Android requiere: app adicional (Termux + git), commits manuales, conexión a internet
- Syncthing permite: trabajar sin conexión, sincronizar en segundo plano, detectar cambios al vuelo
- Trade-off: Necesitas un Mac intermedio entre Android y GitHub
¿Por qué watchexec + launchd en lugar de cron o sync-obsidian.js?
- cron revisa cada N minutos (mínimo 1 minuto) → retraso innecesario
- watchexec usa
fsevents(API nativa de macOS) → detecta cambios en milisegundos - sync-obsidian.js (chokidar) funcionaba igual, pero requería Node.js corriendo permanentemente y no persistía tras reinicio
- launchd soluciona el problema de persistencia: watchexec se reinicia automáticamente al iniciar sesión
- Sin launchd: cada reinicio del Mac requería ejecutar
nohup watchexec ... &manualmente
¿Por qué no build en el móvil?
- Principio: “El móvil solo escribe, la nube construye”
- Astro + Node.js no funcionan en Android (no hay runtime completo)
- El build requiere: 20+ dependencias npm, mucha RAM, tiempo de CPU
- La nube (GitHub Actions + Cloudflare Pages) hace el build gratis y rápido
¿Por qué Cloudflare Pages?
- Deploy automático desde GitHub Actions
- CDN global (rápido en cualquier país, tiempo de carga <1s)
- Free tier generoso (500 builds/mes, ancho de banda ilimitado)
- Integración nativa con GitHub
7. Notas importantes
Rutas de corchetes en zsh
Cuando trabajes con rutas que contienen corchetes (como [category]), el shell zsh interpreta los corchetes como patrones de globbing. Usa comillas simples:
# ❌ MAL (zsh interpreta [category] como un patrón)
ls src/pages/category/[category]/index.astro
# ✅ BIEN (comillas simples evitan la interpretación)
ls 'src/pages/category/[category]/index.astro'
ls src/pages/category/\[category\]/index.astro
nohup.out y logs
El archivo nohup.out ya no se usa (watchexec ahora es gestionado por launchd). Si aparece, se puede eliminar:
rm nohup.out
Los logs de watchexec están en:
/tmp/watchexec.log— actividad normal/tmp/watchexec.err— errores
Versiones del sistema
| Herramienta | Ruta | Versión |
|---|---|---|
| Node.js | /usr/local/bin/node | 22.22.3 |
| npm | /usr/local/bin/npm | 10.9.8 |
| watchexec | /opt/homebrew/bin/watchexec | 2.5.1 |
| launchd | (incluido en macOS) | — |
| Syncthing (Mac) | App gráfica | [PENDIENTE] |
| Syncthing (Android) | App de F-Droid/Play Store | [PENDIENTE] |
| Git | /usr/bin/git | (incluido en macOS) |
| Obsidian (Mac) | App | [PENDIENTE] |
| Obsidian (Android) | App de Play Store | [PENDIENTE] |