Deploy de Astro en GitHub Pages con CI/CD.
Qué es GitHub Pages
Hosting gratuito de sitios estáticos directo desde un repositorio de GitHub. Soporta deploy manual (desde una rama) o automático via GitHub Actions. Ideal para proyectos que generan HTML estático en build time — exactamente lo que hace Astro.
Por qué GitHub Pages
Tengo un proyecto Astro que es un conjunto de herramientas web que corren 100% client-side. No hay backend, no hay base de datos. Es un sitio estático puro.
Evaluación rápida:
- Vercel / Netlify — Excelentes, pero crean una capa más: otra cuenta, otro dashboard, otro login. Para un sitio estático sin funciones serverless, es infraestructura innecesaria.
- Cloudflare Pages — Mismo caso. Muy bueno, pero no necesito CDN enterprise ni Workers para un sitio de herramientas.
- GitHub Pages — El código ya está en GitHub. El CI/CD es GitHub Actions. Todo queda en un solo lugar. Para un sitio estático sin requerimientos especiales, es la opción más simple.
Configuración
1. Configurar Astro para GitHub Pages
Astro necesita saber dos cosas: la URL del sitio y el path base (porque GitHub Pages sirve en tu-usuario.github.io/nombre-repo/, no en la raíz).
// astro.config.mjs
export default defineConfig({
site: "https://TU_USUARIO.github.io", // <- cambiá esto por tu usuario
base: "/TU_REPO", // <- cambiá esto por el nombre de tu repo
// ... resto de tu config
});
Gotcha importante:
import.meta.env.BASE_URLdevuelve el valor debaseSIN trailing slash. Si tu base es/webtools, el valor es/webtools, no/webtools/. Todos tus links internos tienen que concatenar con/explícito:`${base}/image`, no`${base}image`. Si no, vas a terminar con rutas como/webtoolsimage.
2. Actualizar links internos
En archivos .astro, usá import.meta.env.BASE_URL para construir las rutas:
---
const base = import.meta.env.BASE_URL;
---
<a href={base}>Home</a>
<a href={`${base}/image`}>Images</a>
<a href={`${base}/audio`}>Audio</a>
En componentes React (o cualquier framework), funciona igual — Vite lo reemplaza en build time:
const base = import.meta.env.BASE_URL;
const tools = [
{ href: `${base}/image`, title: "Image Optimizer" },
{ href: `${base}/audio`, title: "Audio Optimizer" },
];
3. Crear el workflow de GitHub Actions
# .github/workflows/deploy.yml
name: Deploy to GitHub Pages
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run build
- uses: actions/upload-pages-artifact@v3
with:
path: dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
Dos jobs separados: build compila el sitio, deploy lo sube a Pages. El concurrency cancela deploys anteriores si pusheás rápido varias veces.
4. Crear el repo y pushear
gh repo create TU_REPO --public --source=. --push # <- cambiá TU_REPO por el nombre
Si es la primera vez que pusheás un archivo en
.github/workflows/, tu token deghnecesita el scopeworkflow. Si te da error de permisos, corré:gh auth refresh -s workflow -h github.comy volvé a pushear.
5. Habilitar GitHub Pages con Actions como source
Desde la terminal:
gh api repos/TU_USUARIO/TU_REPO/pages -X POST --input - <<'EOF'
{"build_type":"workflow","source":{"branch":"main","path":"/"}}
EOF
O desde GitHub: Settings > Pages > Source > GitHub Actions.
A partir de acá, cada push a main dispara el workflow automáticamente.
Agregar Sentry (error tracking)
1. Instalar el SDK
npm install @sentry/astro @sentry/browser
2. Agregar la integración a Astro
// astro.config.mjs
import sentry from "@sentry/astro";
export default defineConfig({
integrations: [
// tus otras integraciones...
sentry(),
],
});
3. Crear el archivo de configuración del cliente
// sentry.client.config.js (en la raíz del proyecto)
import * as Sentry from "@sentry/astro";
Sentry.init({
dsn: "TU_DSN_DE_SENTRY", // <- cambiá esto por tu DSN
tracesSampleRate: 1.0,
replaysSessionSampleRate: 0,
replaysOnErrorSampleRate: 1.0,
});
tracesSampleRate: 1.0— trackea el 100% de las transacciones. Para sitios con mucho tráfico, bajalo a0.1o menos.replaysOnErrorSampleRate: 1.0— graba un replay de la sesión cuando hay un error. Muy útil para debugging.replaysSessionSampleRate: 0— no graba sesiones sin errores. Ahorra quota.
No pases las opciones directo en
sentry()dentro deastro.config.mjs. Está deprecado. Sentry espera el archivosentry.client.config.jsseparado.
Agregar Umami (analytics)
1. Crear el sitio en Umami Cloud
Andá a Umami Cloud, creá un sitio con el dominio TU_USUARIO.github.io (sin https://, sin path). Te va a dar un snippet con un data-website-id.
2. Agregar el script al layout
<!-- src/layouts/Layout.astro — dentro del <head> -->
<script
is:inline
defer
src="https://cloud.umami.is/script.js"
data-website-id="TU_WEBSITE_ID"
></script>
El
is:inlinees obligatorio en Astro. Sin él, Astro intenta procesar el script (bundlearlo, optimizarlo) y rompe porque tiene atributos custom (data-website-id).is:inlinele dice “dejá este script tal cual en el HTML”.
Eso es todo. Umami es un script de 2KB que no usa cookies y es GDPR-compliant. No necesitás banner de cookies.
SEO básico
Ya que estás configurando el deploy, aprovechá para agregar lo mínimo de SEO:
npx astro add sitemap --yes
Esto genera un sitemap-index.xml automáticamente en cada build. Después creá un robots.txt en public/:
User-agent: *
Allow: /
Sitemap: https://TU_USUARIO.github.io/TU_REPO/sitemap-index.xml
Y asegurate de que tu layout tenga Open Graph tags para que los links se vean bien cuando se comparten:
---
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
---
<meta property="og:type" content="website" />
<meta property="og:url" content={canonicalURL} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<link rel="canonical" href={canonicalURL} />
Resultado
El flujo queda así: pusheás a main, GitHub Actions hace build y deploy en menos de un minuto. Sentry te avisa si algo se rompe. Umami te dice quién visita qué. Todo sin pagar un peso.