Insights / Artículos técnicos
Trampas y soluciones de Astro View Transitions — Guía de mejora de UX y calidad de código
Soluciones para el problema de scripts que dejan de funcionar con View Transitions de Astro, implementación de búsqueda de texto completo con Pagefind, mejora de seguridad de tipos TypeScript, gestión centralizada de constantes y más. Guía práctica de mejora de UX y calidad de código.

Contenido
- Introducción
- Problema de scripts con View Transitions
- Por qué los scripts dejan de funcionar
- Patrón de solución
- Diferencia entre astro:after-swap y astro:page-load
- Implementación de búsqueda de texto completo con Pagefind
- Configuración básica
- Búsqueda por facetas
- Modal de búsqueda
- Integración con SearchAction
- Configuración de caché
- Eliminación de onclick inline
- Patrón de mejora
- Organización de la biblioteca de componentes
- Mejora de seguridad de tipos TypeScript
- Eliminación de tipos any
- Tipos literales del esquema de contenido
- Aserción as const
- Migración de imports obsoletos
- Gestión centralizada de constantes
- Otras mejoras de UX
- Seguimiento de scroll del índice de contenidos
- Scroll spy
- Paginación
- Anchor links con header sticky
- Resumen
- Serie a la que pertenece este artículo
- Actualización del 6 de octubre de 2026: presentación y estado de las acciones en el Editor
Si el menú o la búsqueda fallan solo tras navegar, compara carga directa y navegación con ClientRouter y revisa la inicialización. Sigue el ciclo de vida de Astro: View Transitions para organizar eventos y comprobar ejecuciones duplicadas, retroceso y avance.
Introducción
View Transitions (ClientRouter) de Astro es una función potente que hace las transiciones de página tan fluidas como una SPA. Sin embargo, al implementarla, surgen problemas como que el menú hamburguesa no se abre, el botón de búsqueda no responde o el slider se detiene.
En este artículo, presentamos las trampas de View Transitions y sus soluciones, así como técnicas prácticas para mejorar la UX y la calidad del código.
Problema de scripts con View Transitions
Por qué los scripts dejan de funcionar
La navegación normal vuelve a cargar el HTML. ClientRouter cambia la ejecución: los scripts de módulo empaquetados se ejecutan una sola vez, mientras que los scripts inline pueden repetirse en algunas navegaciones.
Los siguientes tipos de procesamiento se ven afectados:
- Apertura/cierre del menú hamburguesa
- Handler de clic del botón de búsqueda
- Slider de imagen hero
- Seguimiento de scroll del índice de contenidos
- Patrón facade de embed de YouTube
Patrón de solución
Unificar todos los scripts en funciones con nombre y re-registrarlos con astro:after-swap.
<script>
function initHeader() {
const menuBtn = document.querySelector("[data-menu-toggle]");
menuBtn?.addEventListener("click", () => {
/* ... */
});
}
// Ejecución inicial
initHeader();
// Re-ejecución después de View Transitions
document.addEventListener("astro:after-swap", initHeader);
</script>
Diferencia entre astro:after-swap y astro:page-load
astro:after-swap: Se dispara justo después del intercambio del DOM. No se dispara en la carga inicial, por lo que es necesario llamar directamente a la funciónastro:page-load: Se dispara tanto en la carga inicial como después de View Transitions. Se puede omitir la llamada inicial
Para casos como el embed de YouTube donde se necesita que funcione de forma segura también en la carga inicial, astro:page-load es conveniente.
Implementación de búsqueda de texto completo con Pagefind
Para implementar búsqueda de texto completo en un sitio estático, Pagefind es recomendable. Genera el índice en el build y ejecuta la búsqueda en el navegador, siendo rápido y sin necesidad de servidor.
Configuración básica
{
"scripts": {
"build": "astro build && pagefind --site dist"
}
}
Se ejecuta Pagefind después del build de Astro, generando el índice en dist/pagefind/.
Búsqueda por facetas
Con el atributo data-pagefind-filter, se puede filtrar por los 3 ejes de autor, año y tag.
<span data-pagefind-filter="author">gui</span>
<span data-pagefind-filter="year">2026</span>
<span data-pagefind-filter="tag">Astro</span>
Modal de búsqueda
Se implementa un modal de búsqueda que se abre con el atajo Ctrl+K. Cuando no hay resultados, se muestran enlaces al listado de artículos, página de servicios y contacto, para prevenir la salida del usuario.
Integración con SearchAction
Google retiró el cuadro de búsqueda de enlaces de sitio en 2024-11 (anuncio oficial). Trata SearchAction existente como implementación histórica, sin esperar ese cuadro en resultados. Abrir el modal desde ?q= sigue siendo útil para enlaces compartidos y búsqueda interna.
Configuración de caché
Los archivos del índice de Pagefind tienen baja frecuencia de cambio, por lo que se habilita la caché en los headers de Cloudflare Pages.
/pagefind/*
Cache-Control: public, max-age=604800, stale-while-revalidate=86400
Eliminación de onclick inline
Escribir onclick="..." directamente en HTML es práctico, pero causa la necesidad de unsafe-inline en CSP (Content Security Policy).
Patrón de mejora
Reemplazar onclick con atributos data-* + addEventListener.
<!-- Antes -->
<button onclick="window.openSearch?.()">Buscar</button>
<!-- Después -->
<button data-search-trigger>Buscar</button>
document.querySelectorAll("[data-search-trigger]").forEach((btn) => {
btn.addEventListener("click", () => window.openSearch?.());
});
Organización de la biblioteca de componentes
Tener componentes listos para usar al escribir artículos de blog aumenta la expresividad.
| Componente | Uso |
|---|---|
| Callout | Anotaciones de 4 tipos: info / warning / tip / note |
| Timeline | Visualización cronológica de eventos |
| FAQ | Preguntas y respuestas con datos estructurados |
| Gallery | Galería de imágenes con Lightbox |
| CompareTable | Tabla de comparación antes/después |
| ProcessFigure | Diagrama de proceso paso a paso |
| LinkCard | Tarjeta de enlace externo estilo OGP |
| YouTubeEmbed | Carga diferida con patrón facade |
Todos están diseñados para ser invocados desde el frontmatter del Markdown. Si existe data.callout en la plantilla del artículo, se renderiza un <Callout>.
Mejora de seguridad de tipos TypeScript
Eliminación de tipos any
Cambiar any[] → CollectionEntry<'blog'>[] con tipos concretos. Se habilita la autocompletación del IDE y la detección de errores en compilación, haciendo seguros los accesos a propiedades en las plantillas.
Tipos literales del esquema de contenido
type: z.enum(["info", "warning", "tip", "note"]).default("info");
Al definir los valores del frontmatter como unión de tipos literales, las bifurcaciones como if (callout.type === 'info') en la plantilla se vuelven type-safe.
Aserción as const
Al agregar as const a objetos constantes, las propiedades se vuelven readonly y la inferencia de tipos se convierte en tipo literal. Siempre agreguelo a la constante SITE.
Migración de imports obsoletos
La documentación actual de Astro importa z para los esquemas de contenido desde astro/zod. Consulte la guía de colecciones de contenido.
Gestión centralizada de constantes
Los valores hardcodeados causan omisiones al hacer cambios. Se consolidaron los siguientes valores en src/data/site.ts.
| Constante | Número de ubicaciones antes de centralizar |
|---|---|
| AdSense Client ID | 4 archivos |
| GA4 Measurement ID | 2 ubicaciones |
| ID de slot de publicidad | 4 archivos |
| URLs sociales (X, GitHub, Discord, Aceserver) | 17 ubicaciones |
| Teléfono, email, LINE | 3 archivos |
export const SITE = {
name: "Acecore",
url: "https://acecore.net",
ga4Id: "G-XXXXXXXXXX",
adsenseClientId: "ca-pub-XXXXXXXXXXXXXXXX",
social: {
x: "https://x.com/acecore",
github: "https://github.com/acecore-systems",
discord: "https://discord.gg/...",
},
} as const;
Otras mejoras de UX
Seguimiento de scroll del índice de contenidos
Con IntersectionObserver se monitorizan los encabezados del contenido y se resalta el encabezado activo en el índice del sidebar. El punto clave es también hacer scroll del índice mismo con scrollIntoView({ block: 'nearest', behavior: 'smooth' }).
Scroll spy
En páginas con estructura single-page como la de servicios, el ítem activo de la navegación se sigue automáticamente con IntersectionObserver.
Paginación
Paginación automática cada 6 artículos, navegación con puntos suspensivos (1 2 ... 9 10), y enlaces de texto “← Anterior” y “Siguiente →”. La lógica de paginación se centraliza en src/utils/pagination.ts.
Anchor links con header sticky
Un encabezado fijo puede ocultar el destino de un enlace ancla. El siguiente ejemplo de preflight de UnoCSS corresponde a la configuración de entonces; en el entorno actual con Tailwind se aplica CSS con el mismo propósito.
[id] {
scroll-margin-top: 5rem;
}
html {
scroll-behavior: smooth;
}
Resumen
Si se usa View Transitions, lo más importante es unificar el patrón de inicialización de scripts. Comprenda la diferencia entre astro:after-swap / astro:page-load y pruebe todas las interacciones.
En cuanto a calidad de código, la seguridad de tipos TypeScript y la gestión centralizada de constantes contribuyen enormemente a la mantenibilidad a largo plazo. Al principio puede parecer tedioso, pero los beneficios de la autocompletación del IDE se sienten en el desarrollo diario.
Serie a la que pertenece este artículo
Este artículo es parte de la serie “Guía de mejora de calidad de sitios Astro”. Las mejoras de rendimiento, SEO y accesibilidad también se presentan en artículos individuales.
Actualización del 6 de octubre de 2026: presentación y estado de las acciones en el Editor
En una mejora anonimizada del Editor se ajustaron el cambio de categoría en pantallas estrechas, la navegación fija, las indicaciones para teclado, las etiquetas de los campos y el foco. El estado público o privado también se sincroniza con el estado de la API y la instantánea pública, en vez de deducirse del aspecto del botón.
Si falta el contexto de autenticación o el contrato entre frontend y backend, la interfaz no indica que el guardado se completó; comunica que hace falta recargar o volver a autenticarse. Que una pantalla vacía de importación esté bien presentada no demuestra la aceptación completa de importar datos reales, guardarlos y publicarlos. El alcance de entrada se describe en Importación de perfiles y los límites del CSS público en Diseño seguro de temas.
Al reorganizar nombres o categorías, hay que alinear los valores existentes, la API, los filtros y los cambios en la base de datos. Si no hay datos antiguos, no debe afirmarse que se migró contenido real. Si una insignia de estado enlaza con detalles, debe poder activarse tanto con clic como con Enter. Al editar en línea un identificador de URL pública, también se conservan las comprobaciones de formato, duplicados y actualización de la URL. La visualización pública, la reproducción de medios y la invitación a iniciar sesión en modo anónimo se comprobaron por separado de la aceptación de guardar el identificador o cambiar el estado público en el Editor autenticado.
Al reorganizar el área de edición conforme a las nuevas tareas de la persona usuaria, se separan la navegación persistente y el espacio de trabajo; no basta con cambiar los nombres y dejar las acciones antiguas. Los valores auxiliares, como los saldos, pueden tener menos peso visual que las acciones principales, pero deben mantener un tamaño de texto y un contraste legibles.
- Acción en el Editor Mover una categoría o elegir una unidad de trabajo cambia el estado de edición en pantalla.
- API y snapshot publicado Compruebe el resultado de la API y el snapshot público. No muestre éxito si falla la solicitud o falta el contexto de autenticación.
- Estado después de recargar Muestre solo el estado confirmado y solicite recarga o reautenticación cuando haga falta. La aceptación de guardar y publicar por usuarios con sesión sigue sin verificarse.
Proceso de mejora de UX
Descubrimiento de problemas
Listar los fallos de funcionamiento tras implementar View Transitions.
Unificación de patrones
Convertir todos los scripts a un patrón de inicialización unificado.
Implementación de búsqueda
Implementar búsqueda de texto completo con Pagefind y organizar las vías de acceso.
Garantía de seguridad de tipos
Eliminar tipos any y gestión centralizada de constantes para mejorar la mantenibilidad.
Comparación antes y después de la mejora
Antes de la mejora
- El menú hamburguesa no funciona tras la transición de página
- Sin búsqueda interna del sitio
- Tipos any y constantes hardcodeadas dispersas
- Riesgo de violación CSP con onclick inline
Después de la mejora
- Todos los scripts funcionan correctamente con astro:after-swap
- Búsqueda de texto completo con filtros en 3 ejes con Pagefind
- Seguridad de tipos TypeScript y gestión centralizada de constantes
- Conformidad CSP con addEventListener + atributos data
Preguntas frecuentes
¿Estas mejoras son válidas sin View Transitions?
Las mejoras distintas al patrón de inicialización de scripts (Pagefind, TypeScript, gestión de constantes) son válidas independientemente de si se usa View Transitions o no.
¿Hasta qué escala de sitio puede manejar Pagefind?
Pagefind está diseñado para sitios estáticos y funciona rápidamente incluso con sitios de miles de páginas. El índice de búsqueda se genera en el build y se ejecuta en el navegador, por lo que no hay carga en el servidor.
¿Los errores de tipo TypeScript funcionan si se ignoran?
Funcionan, pero los errores de tipo son señales previas de bugs. Especialmente al hacer type-safe los esquemas de contenido de Astro, se habilita la autocompletación del IDE al acceder a propiedades en las plantillas, mejorando significativamente la eficiencia de desarrollo.