wavival.dev
wavival.dev es mi portafolio y también un caso de diseño. El sistema se llama @wavival | Design System v4: la página se lee como un índice editorial, con reglas de 1px en lugar de cajas, titulares grandes en Raleway 800, índices numerados y una sola señal azul sobre un campo tranquilo. Nació en Claude Design como prototipo y sistema de diseño, y se llevó al código con paridad de tokens. Es bilingüe (español en la raíz, inglés bajo /en), estático y oscuro por defecto.
Por Valentina Ramírez
Publicado: 1 de octubre de 2026 · Actualizado: 2 de octubre de 2026
Este portfolio como caso de diseño: el sistema @wavival | Design System v4, editorial y estático, con reglas en lugar de cajas, una sola señal azul y contraste AA en ambos temas. Bilingüe, sobre Astro y Tailwind, diseñado en Claude Design.
- Astro
- TypeScript
- Tailwind CSS
- Vercel
- Playwright
El problema
Un portafolio de desarrolladora suele terminar como plantilla: tarjetas con sombra, acentos de color que no pasan contraste, animación que compite con el contenido y un diseño que en el código ya no se parece al prototipo. Necesitaba un sitio que fuera en sí mismo la prueba de mi criterio técnico y de diseño: rápido, accesible, bilingüe y con una identidad reconocible.
Plantilla genérica
Tarjetas con sombra y radios por todas partes: se ve como cualquier otro portafolio.
Contraste frágil
El azul de acento anterior solo llegaba a 3,24:1 con texto blanco, por debajo de AA.
Decoración sobre contenido
Animación al hacer scroll e iconos en cada enlace compiten con lo que importa.
Prototipo y código distintos
El diseño dice una cosa y el sitio publicado otra, porque nada obliga a mantenerlos iguales.
Qué construí
- 01
Astro 7 con salida estática y TypeScript. Tailwind 3 mapeado a tokens CSS, y scripts de cliente en TypeScript vanilla solo para el tema, el menú móvil y los filtros de proyectos.
- 02
Estructura atómica (átomos, moléculas, organismos y una plantilla única). Los organismos reciben el idioma y las rutas localizadas salen de una sola función.
- 03
i18n propio: español en la raíz e inglés bajo /en, con el mapa de slugs como única fuente de verdad para el selector de idioma, el sitemap y los hreflang.
- 04
Contenido tipado (proyectos y stack) con campos paralelos para inglés. Todos los casos de estudio se generan desde un solo arreglo.
- 05
SEO y descubrimiento: JSON-LD con Person, Organization y WebSite, OpenGraph por proyecto, sitemap con alternates recíprocos y llms.txt para asistentes de IA.
- 06
Rendimiento: fuentes autohospedadas en subconjunto latino, precarga de la imagen LCP solo donde se usa y View Transitions entre rutas. Core Web Vitals se reportan a Umami cuando hay configuración.
- 07
Seguridad de cabeceras: CSP por hashes, sin unsafe-inline en scripts, con una guardia en CI que recalcula los hashes de cada script inline.
- 08
Despliegue en Vercel con microfrontends (el portafolio y NullBreach comparten dominio) y una única función serverless para el formulario de cotización, que envía por Brevo.
- 09
Flujo dev, stg y main con commitlint, pruebas E2E con Playwright, Lighthouse CI y verificación de enlaces como puertas de calidad.
Diseño
- 01
Sistema @wavival | Design System v4: la página se lee como un índice editorial, con una señal azul sobre un campo tranquilo.
- 02
Diseñado en Claude Design, con un prototipo navegable y un sistema de diseño propio. El sitio replica el prototipo token a token.
- 03
Reglas, no cajas: la estructura sale de líneas de 1px. No hay sombras, las superficies tienen radio 0 y los controles 2px.
- 04
Una sola señal azul con roles separados: un azul para texto, íconos y foco; otro para rellenos y texto grande; otro para los índices; y otro para el botón primario. Cada uno pasa contraste en su uso.
- 05
Escala editorial: Raleway 800 en tamaños fluidos con interlineado de 0,9 a 1 en titulares y tracking negativo; Poppins para el cuerpo. Ambas autohospedadas.
- 06
Índices numerados (01, 02) como guía de lectura, y cada sección abre con una regla de 1px.
- 07
Una columna al ancho completo del contenedor (1280px), con el ritmo vertical definido por tokens de espacio.
- 08
Íconos solo donde funcionan: en los botones de solo ícono y en el botón primario. Los enlaces y botones de texto no llevan flechas.
- 09
El estado se dice con texto: el acordeón es un details nativo que muestra "Ver" y "Cerrar" en lugar de un chevron.
- 10
Oscuro por defecto y alternable. Un script previo al primer pintado aplica el tema sin parpadeo, el tema va por clase y no por media query, y el color del navegador se sincroniza.
- 11
La accesibilidad como restricción de diseño: foco visible de 2px, contraste AA calculado por token en ambos temas, objetivos táctiles de 44px, menú móvil con foco atrapado y respeto de prefers-reduced-motion.
- 12
Movimiento mínimo y funcional: sin animación al hacer scroll, solo transiciones cortas, View Transitions entre rutas y un acordeón de 220ms.
- 13
El sistema está documentado: tokens, clases de componente y catálogo viven en DESIGN.md y COMPONENTS.md.
Decisiones de arquitectura
01 Reglas en lugar de cajas VerCerrar
- Contexto
- Las tarjetas con sombra y radio son el patrón por defecto de casi cualquier portafolio.
- Trade-off
- Sin sombras ni radios, la jerarquía depende de la tipografía y el espacio, y exige más cuidado.
- Decisión
- Estructura con líneas de 1px, superficies con radio 0 y listas dibujadas con bordes. La jerarquía la llevan la escala y los índices.
02 Una señal azul, cuatro roles VerCerrar
- Contexto
- El acento anterior solo alcanzaba 3,24:1 con texto blanco y un mismo azul no pasa contraste en texto pequeño y en rellenos a la vez.
- Trade-off
- Cuatro tokens de azul son más para mantener que uno, pero un solo azul obliga a ceder contraste o presencia.
- Decisión
- Un azul por rol (texto y foco, rellenos y texto grande, índices, botón primario). El relleno del botón es igual en ambos temas para que el texto blanco se mantenga sobre 4,5:1.
03 Escala editorial con tipografía autohospedada VerCerrar
- Contexto
- La identidad del sitio depende de titulares grandes y compactos, y de que carguen sin saltos.
- Trade-off
- Autohospedar exige generar los subconjuntos y precargar; una fuente de terceros es más simple pero añade una petición y un punto de falla.
- Decisión
- Raleway variable (600 a 800) y Poppins estática en subconjunto latino y woff2, con font-display swap y precarga solo de los pesos críticos.
04 Estático y sin animación de scroll VerCerrar
- Contexto
- Una animación que oculta contenido hasta que aparece compite con la lectura y con el rendimiento.
- Trade-off
- Un sitio estático se siente menos espectacular, pero el diseño se apoya en la tipografía y el ritmo.
- Decisión
- Sin scroll reveal ni librería de animación. Acordeón nativo con el estado en texto y solo transiciones cortas, todas desactivadas con prefers-reduced-motion.
05 Oscuro por defecto, por clase VerCerrar
- Contexto
- Seguir la preferencia del sistema deja el diseño en manos del dispositivo, y cambiar el tema tras el primer pintado produce un parpadeo.
- Trade-off
- Fijar el oscuro como inicio ignora la preferencia del sistema, y un script inline obliga a mantener el CSP por hashes.
- Decisión
- Un script síncrono al inicio del head aplica la clase dark antes de cargar los estilos, salvo que el usuario haya guardado el tema claro. El CSP incluye el hash de ese script.
06 Español en la raíz, inglés bajo /en VerCerrar
- Contexto
- El sitio atiende a clientes en español y en inglés, y cada página necesita su equivalente.
- Trade-off
- Slugs traducidos mejoran el SEO local pero obligan a mantener el mapeo entre idiomas.
- Decisión
- Slugs en español en la raíz y en inglés bajo /en, con un único mapa que alimenta el selector de idioma, el sitemap y los hreflang.
Resultados
- Sitio bilingüe en producción en www.wavival.dev, con 34 páginas estáticas entre español e inglés.
- Diseño implementado con paridad respecto al prototipo de Claude Design.
- Puertas de calidad en cada cambio: pruebas E2E con Playwright, Lighthouse CI (accesibilidad y SEO con mínimo 0,9), verificación de enlaces rotos, de hashes CSP y de clases CSS.
Aprendizajes
Un sistema de diseño solo vale si se traduce a tokens: cada color y tamaño vive como variable CSS y los componentes no llevan valores sueltos.
El contraste se decide en el token: el acento anterior (3,24:1) obligó a separar un azul por rol.
Tailwind purga las clases construidas por fragmentos (btn-${variant}). Los componentes deben usar nombres de clase completos.
Un backdrop-filter convierte al elemento en contenedor de sus hijos fixed: el menú móvil tuvo que ser hermano del header y no hijo.
Un componente con el mismo nombre que una utilidad de Tailwind arrastra sus estilos donde se use la utilidad: .text-link pasó a llamarse .action-link.
Tu próxima idea merece código que la sostenga.
Diseño y construyo productos completos: del backend a la interfaz que tus usuarios aman. Con IA integrada y seguridad desde el diseño.
Proyectos desde USD 250 / COP 1.000.000 según alcance (MVP desde 3-6 semanas). Disponibilidad limitada, respondo en 24h.