Introducción
Con el portafolio hecho, faltan tres cosas: darle estilo rápido con Tailwind (si lo usas), publicarlo cada vez que haces git push y saber leer un tutorial de Astro antiguo sin que te rompa el proyecto.
Con el portafolio hecho, faltan tres cosas: darle estilo rápido con Tailwind (si lo usas), publicarlo cada vez que haces git push y saber leer un tutorial de Astro antiguo sin que te rompa el proyecto.
npx astro add tailwind deja Tailwind 4 listo; falta importar el CSS con @import "tailwindcss"; en el layout.
En GitHub Pages: site, base, import.meta.env.BASE_URL en los enlaces y el flujo con withastro/action.
En Netlify o Vercel: npm run build y la carpeta dist, sin base.
Solo las variables PUBLIC_ llegan al navegador.
Con el portafolio hecho, faltan tres cosas: darle estilo rápido con Tailwind (si lo usas), publicarlo cada vez que haces git push y saber leer un tutorial de Astro antiguo sin que te rompa el proyecto.
npx astro add tailwind
La orden instala Tailwind 4 y su plugin para Vite, y añade el plugin a astro.config.mjs:
// astro.config.mjs import { defineConfig } from 'astro/config'; import tailwindcss from '@tailwindcss/vite'; export default defineConfig({ vite: { plugins: [tailwindcss()], }, });
Después, un CSS con @import "tailwindcss"; (por ejemplo src/styles/global.css) importado en el layout, como cualquier CSS global. Ya puedes usar las clases en los componentes:
En GitHub Pages la web suele quedar en una subcarpeta: https://luciaprieto.github.io/portafolio/. Astro tiene que saberlo para escribir bien las direcciones:
// astro.config.mjs export default defineConfig({ site: 'https://luciaprieto.github.io', base: '/portafolio', });
Con base, los enlaces internos llevan delante la subcarpeta. No la escribas a mano: sale de import.meta.env.BASE_URL, que vale /portafolio con base y / sin él. Quítale la barra final y el enlace funciona en los dos casos:
--- const base = import.meta.env.BASE_URL.replace(/\/$/, ''); --- <a href={`${base}/proyectos/${proyecto.id}`}>{titulo}</a>
Las dos detectan Astro solas al conectar el repositorio:
AjusteValor Orden de construcciónnpm run build Carpeta que se publicadist Versión de Node.js22.23.4 o superior (en Netlify, la variable NODE_VERSION; en Vercel, en los ajustes del proyecto)
Aquí no hace falta base: la web queda en la raíz de su dominio.
Una clave o una dirección que cambia según dónde se publica va en un fichero .env, fuera de Git (añádelo a .gitignore):
# .env PUBLIC_FORMULARIO_URL="https://formularios.ejemplo.es/lucia" CLAVE_API="no-la-subas-nunca"
<form action={import.meta.env.PUBLIC_FORMULARIO_URL} method="post">…</form>
Solo las que empiezan por PUBLIC_ llegan al navegador. Las demás solo existen al construir: así una clave no acaba en el HTML que ve todo el mundo. En GitHub Actions, Netlify o Vercel se ponen en los ajustes del proyecto, no en el repositorio.
npx @astrojs/upgrade
Actualiza Astro y sus integraciones a la vez. Antes de un cambio de versión mayor (de la 7 a la 8), lee su guía de actualización, haz commit para poder volver atrás y comprueba con npm run build.
Astro cambia rápido y muchos tutoriales y respuestas de IA están escritos para versiones anteriores. Si algo no funciona, mira esta tabla:
En un tutorial antiguoAhora (Astro 6 y 7) src/content/config.tssrc/content.config.ts, con un loader en cada colección import { z } from 'astro:content'import { z } from 'astro/zod' entrada.slug, getEntryBySlug()entrada.id, getEntry() entrada.render()render(entrada), importado de astro:content Astro.glob('./posts/*.md')import.meta.glob('./posts/*.md', { eager: true }) o una colección <ViewTransitions /><ClientRouter /> @astrojs/tailwind y tailwind.config.mjsnpx astro add tailwind (Tailwind 4) z.string().email()z.email() (Zod 4) Node.js 18 o 20Node.js 22.23.4 o superior
Y dos cambios de Astro 7 que pueden sorprenderte:
Una etiqueta sin cerrar (un <p> sin su </p>) es un error al construir. Al comprimir el HTML, el salto de línea entre dos etiquetas desaparece: <span>Lucía</span> y <em>Prieto</em> en dos líneas se ven pegados, «LucíaPrieto». Si quieres el espacio, escríbelo: {' '}.
Configura site y base para GitHub Pages y cambia los enlaces internos para que usen base. Añade el flujo deploy.yml, activa Pages con GitHub Actions y publica. Abre la web publicada y comprueba que funcionan los enlaces, las imágenes y las transiciones. Haz un cambio pequeño, git push, y mira cómo se vuelve a publicar sola. Busca un tutorial de Astro de 2024 o anterior y apunta dos cosas que ya no se escriben así.
Olvidar base en GitHub Pages: la portada se ve sin estilos y los enlaces llevan a un 404. Escribir /proyectos/... a mano en los enlaces con base: falta la subcarpeta. No subir package-lock.json: el servidor instala otras versiones (ver npm a fondo). Guardar claves en una variable PUBLIC_: llegan al navegador y cualquiera las lee. Copiar de un tutorial antiguo sin mirar la versión.
Con el portafolio hecho, faltan tres cosas: darle estilo rápido con Tailwind (si lo usas), publicarlo cada vez que haces git push y saber leer un tutorial de Astro antiguo sin que te rompa el proyecto.
Código del tema: npx astro add tailwind
Con el portafolio hecho, faltan tres cosas: darle estilo rápido con Tailwind (si lo usas), publicarlo cada vez que haces git push y saber leer un tutorial de Astro antiguo sin que te rompa el proyecto.
npx astro add tailwindLa orden instala Tailwind 4 y su plugin para Vite, y añade el plugin a astro.config.mjs:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
vite: {
plugins: [tailwindcss()],
},
});Después, un CSS con @import "tailwindcss"; (por ejemplo src/styles/global.css) importado en el layout, como cualquier CSS global. Ya puedes usar las clases en los componentes:
<article class="overflow-hidden rounded-lg border border-stone-200 bg-white">
<h2 class="p-4 text-xl font-semibold">{titulo}</h2>
</article>Si en un tutorial ves @astrojs/tailwind y un fichero tailwind.config.mjs, es la forma antigua, de Tailwind 3. No la mezcles con la nueva.
En GitHub Pages la web suele quedar en una subcarpeta: https://luciaprieto.github.io/portafolio/. Astro tiene que saberlo para escribir bien las direcciones:
// astro.config.mjs
export default defineConfig({
site: 'https://luciaprieto.github.io',
base: '/portafolio',
});Con base, los enlaces internos llevan delante la subcarpeta. No la escribas a mano: sale de import.meta.env.BASE_URL, que vale /portafolio con base y / sin él. Quítale la barra final y el enlace funciona en los dos casos:
---
const base = import.meta.env.BASE_URL.replace(/\/$/, '');
---
<a href={`${base}/proyectos/${proyecto.id}`}>{titulo}</a>Las imágenes de <Image /> y los CSS ya salen con la subcarpeta: Astro lo hace solo.
Ahora el flujo de trabajo, en .github/workflows/deploy.yml. Es el de la documentación de Astro (así en noviembre de 2026; las versiones de las acciones pueden haber cambiado):
name: Publicar en GitHub Pages
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Descargar el repositorio
uses: actions/checkout@v7
- name: Instalar, construir y subir la web
uses: withastro/action@v6
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Publicar
id: deployment
uses: actions/deploy-pages@v5package-lock.json: la acción instala con él).git push. En la pestaña Actions verás el flujo; cuando termine en verde, la web está publicada.Con dominio propio: un fichero public/CNAME con una línea (luciaprieto.es), site con ese dominio y sin base. Los registros DNS están en DNS paso a paso.
Las dos detectan Astro solas al conectar el repositorio:
| Ajuste | Valor |
|---|---|
| Orden de construcción | npm run build |
| Carpeta que se publica | dist |
| Versión de Node.js | 22.23.4 o superior (en Netlify, la variable NODE_VERSION; en Vercel, en los ajustes del proyecto) |
Aquí no hace falta base: la web queda en la raíz de su dominio.
Una clave o una dirección que cambia según dónde se publica va en un fichero .env, fuera de Git (añádelo a .gitignore):
# .env
PUBLIC_FORMULARIO_URL="https://formularios.ejemplo.es/lucia"
CLAVE_API="no-la-subas-nunca"<form action={import.meta.env.PUBLIC_FORMULARIO_URL} method="post">…</form>Solo las que empiezan por PUBLIC_ llegan al navegador. Las demás solo existen al construir: así una clave no acaba en el HTML que ve todo el mundo. En GitHub Actions, Netlify o Vercel se ponen en los ajustes del proyecto, no en el repositorio.
npx @astrojs/upgrade Actualiza Astro y sus integraciones a la vez. Antes de un cambio de versión mayor (de la 7 a la 8), lee su guía de actualización, haz commit para poder volver atrás y comprueba con npm run build.
Astro cambia rápido y muchos tutoriales y respuestas de IA están escritos para versiones anteriores. Si algo no funciona, mira esta tabla:
| En un tutorial antiguo | Ahora (Astro 6 y 7) |
|---|---|
src/content/config.ts | src/content.config.ts, con un loader en cada colección |
import { z } from 'astro:content' | import { z } from 'astro/zod' |
entrada.slug, getEntryBySlug() | entrada.id, getEntry() |
entrada.render() | render(entrada), importado de astro:content |
Astro.glob('./posts/*.md') | import.meta.glob('./posts/*.md', { eager: true }) o una colección |
<ViewTransitions /> | <ClientRouter /> |
@astrojs/tailwind y tailwind.config.mjs | npx astro add tailwind (Tailwind 4) |
z.string().email() | z.email() (Zod 4) |
| Node.js 18 o 20 | Node.js 22.23.4 o superior |
Y dos cambios de Astro 7 que pueden sorprenderte:
<p> sin su </p>) es un error al construir.<span>Lucía</span> y <em>Prieto</em> en dos líneas se ven pegados, «LucíaPrieto». Si quieres el espacio, escríbelo: {' '}.💡 Consejo. Cuando pidas ayuda a una IA con Astro, dile la versión (npm ls astro) y pídele que siga la documentación de esa versión. Comprueba lo que te da con esta tabla.
site y base para GitHub Pages y cambia los enlaces internos para que usen base.deploy.yml, activa Pages con GitHub Actions y publica.git push, y mira cómo se vuelve a publicar sola.base en GitHub Pages: la portada se ve sin estilos y los enlaces llevan a un 404./proyectos/... a mano en los enlaces con base: falta la subcarpeta.package-lock.json: el servidor instala otras versiones (ver npm a fondo).PUBLIC_: llegan al navegador y cualquiera las lee.Abre cada actividad para hacerla aquí mismo. Lo que resuelves se guarda en este navegador.