Disponible para nuevos proyectos
Cuéntame sobre tu marca, tu producto o tu próxima campaña. Reviso cada propuesta personalmente y te respondo con un plan claro en menos de 48 horas.
Colofón
Este sitio es el ejemplo más largo de lo que hago: lo diseñé y lo construí hasta producción. Acá están las decisiones y, sobre todo, el motivo de cada una. Sirve para ver cómo pienso antes de que hablemos.
Next.js sobre el App Router, con la base de datos como fuente de verdad.
Next.js 16, TypeScript, Tailwind y Supabase para datos, sesión y archivos. Casi todo lo que se lee acá sale de un panel propio, no del código: los proyectos, las notas, los testimonios, las listas de herramientas y buena parte del copy. Cambiar una palabra no debería pedir un despliegue.
Una familia con eje variable en vez de un catálogo.
Geist sostiene el sistema entero aprovechando su eje continuo: pesos intermedios en los titulares, el 200 reservado para las cifras, la itálica variable para los acentos, y la mono para los rótulos. Archivo va en el cuerpo. Emparejar dos familias que compiten es más fácil que sacarle voz a una sola.
Un par de marca y un solo color saturado.
Papel y tinta como par, y el rojo como único acento. Hay dos tokens distintos para ese rojo, uno para texto pequeño sobre claro y otro para texto sobre oscuro, porque el mismo valor no llega al contraste mínimo en los dos sitios. Un color que no se puede leer no es un color de marca, es un adorno.
Las entradas las resuelve el compositor, no el hilo principal.
Las apariciones son animaciones CSS que dispara un IntersectionObserver: antes las calculaba JavaScript cuadro a cuadro y en iOS quedaban clavadas a 60fps aunque la pantalla fuera de 120. Nada de esto se mueve si el sistema pide menos movimiento.
Tener sesión y ser admin son cosas distintas.
El endpoint de registro de Supabase responde con una clave pública, así que cualquiera puede crearse una cuenta: si las políticas de escritura confiaran en «estar autenticado», estarían abiertas. Acá preguntan por una función que vive en un esquema que la API no publica, y la lista de administradores no se llega a leer desde fuera.
Cada URL sirve un contenido estable, sin adivinar.
El sitio no redirige según el idioma del navegador ni la ubicación: el cambio es explícito. Adivinar deja a Googlebot, que rastrea desde Estados Unidos, viendo la portada como una redirección, y a un visitante compartiendo un enlace que a otro le abre en otro idioma.
Se audita la página renderizada, no el código.
Cada corrida de tests abre las páginas reales en un navegador y las pasa por axe-core en móvil y escritorio. En la primera pasada encontró dos fallos serios que el build, el typecheck y los tests dejaban pasar sin decir nada, porque ninguna de esas herramientas mira la página.
Publicar es un push, y el buscador se entera solo.
Producción sale de la rama principal en Vercel. Al publicar un proyecto, el sitio avisa a los buscadores por IndexNow y regenera solo las páginas afectadas. El sitemap se arma desde la base con sus equivalencias de idioma, así que no hay una lista de URLs que mantener a mano.