Qué problema resuelve este artículo

Muchos blogs personales no se frenan porque construir el sitio sea difícil. Se frenan porque publicar se siente pesado. Cada nuevo post implica tocar configuración, reconstruir a mano, subir archivos manualmente y repetir los mismos pasos de despliegue.

Yo quería un flujo más ligero: escribir Markdown en local, hacer push a GitHub y dejar que GitHub Actions construyera y publicara el sitio automáticamente. Así publicar se convierte en un hábito repetible en lugar de una pequeña tarea de operaciones cada vez.

Cuándo encaja este modelo

  • Tienes un blog personal, una publicación técnica o un sitio ligero estilo documentación
  • Quieres que el contenido viva como archivos Markdown dentro de Git
  • No quieres WordPress ni un backend CMS pesado
  • Quieres contenido bilingüe sin mantener mapas manuales de traducción

Si necesitas primero un backend editorial visual, aprobación multi-autor o edición online, probablemente este no sea el mejor modelo.

Resultado final

Una vez configurado el workflow, publicar un nuevo artículo queda así:

  1. Generar localmente un esqueleto bilingüe
  2. Editar los archivos Markdown chino e inglés
  3. Previsualizar el sitio en local
  4. git push origin main
  5. Dejar que GitHub Actions despliegue la actualización

Esa separación importa. La escritura se mantiene centrada en el contenido y el despliegue pasa a ser automatización.

Checklist del entorno

El stack actual de este blog es:

  • Framework: Astro
  • Capa de contenido: astro:content
  • Formato: Markdown
  • Modelo de despliegue: release de artefactos estáticos
  • Servidor web: Nginx
  • CI/CD: GitHub Actions

Los posts viven en una estructura bilingüe:

src/content/posts/zh-cn/*.md
src/content/posts/en-us/*.md

Cada idioma tiene su propio archivo, pero ambos comparten el mismo path, así que el sitio genera:

  • Chino: /posts/<path>/
  • Inglés: /en/posts/<path>/

Instrucciones paso a paso

1. Fija pronto el modelo de contenido

Si el modelo de contenido cambia continuamente, cada nuevo artículo se convierte en una tarea de código en vez de una tarea de escritura.

En este proyecto, posts, pages, categories y resources viven en astro:content. La regla más importante es:

  • los posts usan path
  • pages y categories usan key

Eso significa que añadir un artículo nuevo solo debería requerir añadir archivos Markdown, no tocar la lógica de routing.

2. Añade un comando para crear el esqueleto del post

Copiar archivos antiguos a mano funciona durante un tiempo, pero termina volviéndose desordenado.

Añadí un script sencillo para poder crear un artículo así:

npm run new:post -- "markdown-blog-publish-workflow" "本地写 Markdown,git push 后自动上线:我的双语博客发布流程" "Write Markdown Locally, Deploy on git push: My Bilingual Blog Publishing Workflow" writing

Esto crea inmediatamente dos borradores:

src/content/posts/zh-cn/markdown-blog-publish-workflow.md
src/content/posts/en-us/markdown-blog-publish-workflow.md

Se crean con:

draft: true

Ese valor por defecto importa porque evita publicar automáticamente contenido a medio escribir.

3. Mantén el trabajo local centrado en escribir y previsualizar

Mientras escribo solo me importan dos cosas:

  1. editar Markdown
  2. previsualizar con npm run dev

Las comprobaciones locales son sencillas:

  • aparece el post en la página principal
  • renderizan correctamente ambas versiones
  • categorías y tags agregan bien
  • title y description funcionan para SEO

Si esta fase está sólida, no hay una buena razón para seguir haciendo despliegues manuales por SSH.

4. Entrega el despliegue a GitHub Actions

Esta es la parte que convierte el flujo en algo sostenible.

El workflow de producción actual es:

  1. push a main
  2. ejecutar npm ci
  3. ejecutar npm run build
  4. archivar dist
  5. subir por SSH
  6. extraer en un nuevo releases/<timestamp>-<sha>
  7. cambiar current
  8. ejecutar una comprobación pública de disponibilidad

A partir de ahí publicar un artículo deja de ser una tarea manual de release. Es CI/CD estándar.

5. Deja que el servidor solo sirva archivos estáticos

Hay un principio que me importa especialmente: el servidor debería servir, no construir.

Eso tiene varias ventajas inmediatas:

  • menos piezas móviles en producción
  • entorno de build más consistente
  • rollback más sencillo
  • debugging más claro cuando algo falla

La estructura en producción queda así:

/var/www/aitokenhacks.com/releases/<release-id>
/var/www/aitokenhacks.com/current

Cada release está aislada y publicar consiste básicamente en cambiar un symlink.

6. Añade diagnósticos al workflow de despliegue

La automatización no está terminada porque exista un YAML. Solo se vuelve útil cuando los fallos son fáciles de entender.

Por eso añadí diagnósticos para cosas como:

  • qué deploy secret falta
  • si el acceso SSH funciona
  • si existen los directorios remotos
  • a qué release se cambió current

Así un despliegue fallido no termina en un badge rojo sin contexto. Puedes saber si el problema está en GitHub Secrets, autenticación SSH, permisos del directorio o verificación pública.

Problemas habituales

Por qué no usar simplemente un backend online

Porque el objetivo principal del sitio es acumular contenido y SEO, no optimizar la UX del editor.

Los Markdown gestionados con Git me dan cosas que valoro más:

  • historial completo de versiones
  • rollback
  • cambios revisables
  • contenido junto al código
  • ninguna dependencia de un panel administrativo de terceros

Por qué no guardar ambos idiomas en un solo archivo

Porque un archivo con frontmatter duplicado y cuerpo duplicado se vuelve difícil de mantener muy rápido.

Dos archivos con el mismo path resultaron mucho más limpios:

  • encaja naturalmente con las content collections de Astro
  • el cuerpo sigue siendo fácil de editar
  • no hace falta una capa extra de mapping de traducciones

Qué falla más a menudo en un despliegue automático

En la práctica me encontré con dos clases de problemas recurrentes:

  • problemas de billing o quota de GitHub Actions, donde el job ni siquiera empieza de verdad
  • deploy secrets ausentes o incorrectos, por lo que el setup SSH falla inmediatamente

Por eso mi orden normal de debugging es:

  1. ¿arrancó realmente el workflow?
  2. ¿están presentes los deploy secrets?
  3. ¿funcionan el usuario y la clave SSH?
  4. ¿permite publicar el directorio remoto?

Reflexión final

Si estás construyendo un blog técnico personal, recomiendo separar claramente escritura y mecánica de release.

Al escribir, céntrate en la calidad del artículo. Para publicar, deja los pasos repetitivos en manos de CI/CD.

Cuando el workflow se convierte en “escribe Markdown en local y luego git push”, el blog por fin se vuelve algo en lo que puedes seguir publicando de forma consistente.