¿Qué hace Ahmed UI Craft?
Los modelos de lenguaje tienden hacia el promedio estadístico de la web: Inter, un degradado morado, tres tarjetas redondeadas idénticas, un emoji por característica. Ese resultado es reconocible de inmediato y le dice al usuario que nadie tomó una decisión. Esta habilidad fuerza que se tomen las decisiones, se escriban como tokens y se verifiquen antes de entregar cualquier cosa.
Sigue el flujo de trabajo en orden. Cada paso existe porque saltárselo es como se generan interfaces genéricas.
Paso 0 - Lee el proyecto antes de diseñar
Mira antes de inventar. Revisa, en este orden:
- Framework:
package.json(next, react, vue, svelte, astro), o.htmlplano. - Estilos:
tailwind.config.*o@import "tailwindcss"/@theme(Tailwind v4),*.module.css, styled-components, o CSS plano. - Tokens existentes: busca con grep
--color-,--space-,@theme,theme.extend. - Librería de componentes:
components/ui/+components.json(shadcn/ui),@mui/material, Radix, Headless UI, Vuetify.
Por qué: un componente hermoso que ignora los tokens y la librería existentes del proyecto
es una regresión, no una mejora. Si el proyecto ya tiene un sistema de diseño, trabaja dentro
de él: extiende sus tokens, rediseña sus primitivas (para shadcn/ui, edita las variables CSS
en globals.css y los archivos de componentes, no los envuelvas). Solo usa assets/tokens.css
cuando no haya un sistema que extender.
Si no existe nada, usa por defecto: HTML semántico + propiedades personalizadas CSS desde
assets/tokens.css, mapeadas a Tailwind si Tailwind está presente.
Paso 1 - Pensamiento de diseño (antes de cualquier código)
Escribe cuatro líneas cortas, en tu cabeza o en la respuesta:
- Propósito: ¿qué trabajo hace esta pantalla? (ej. "convencer a un líder de equipo para que inicie una prueba")
- Audiencia: quién mira, en qué dispositivo, con qué estado de ánimo? (ej. "ingenieros de operaciones, escritorio, escaneando rápido")
- Tono: tres adjetivos. (ej. "exacto, calmado, denso")
- Diferenciador: una cosa que alguien recordaría después de cerrar la pestaña.
El diferenciador debe ser concreto y visible, no "limpio y moderno". Buenos ejemplos: "precios establecidos en un enorme numeral condensado que va de borde a borde"; "cada tarjeta tiene una línea fina y un número índice mono como una hoja de especificaciones"; "el título principal está en una serifa itálica sobre una textura de papel color hueso".
Por qué: si no puedes nombrar el diferenciador, el resultado será el promedio, porque el promedio es lo que el modelo produce cuando nada lo aleja.
Si el usuario proporcionó una marca, captura de pantalla o sitio existente, el tono proviene de ahí. No impongas una nueva dirección a una marca establecida.
Paso 2 - Comprométete con una dirección estética
Elige una dirección y aplícala en todas partes: tipo, color, radio, sombra, movimiento, imágenes y ritmo de copia. Las direcciones mixtas se leen como indecisión.
| Dirección | Tipo | Color | Forma y profundidad | Movimiento |
|---|---|---|---|---|
| Editorial | Serifa display, cuerpo humanista | Papel hueso, tinta, un acento fuerte | Líneas finas, radio casi nulo, sin sombras | Fundidos lentos, ninguno al hacer scroll |
| Brutalista | Grotesk pesada o mono, tamaños enormes | Negro/blanco crudo + un color chillón | Radio 0, bordes gruesos, sombras duras descentradas | Instantáneo, rápido |
| Suave / orgánica | Display redondeada o serifa suave | Neutros cálidos teñidos, acento terroso apagado | Radio grande solo en contenedores, sombras difusas | Elástico, suave |
| Industrial / técnica | Condensada o grotesk + mono | Neutro oscuro, acento de señal (ámbar, lima, cian) | Radio pequeño, bordes de 1 píxel, líneas de cuadrícula visibles | Rápido, lineal |
| Lujosa | Serifa de alto contraste, mayúsculas con espaciado amplio | Casi negro, crema, acento metálico o joya profunda | Espacio en blanco generoso, bordes finos | Lento, alivios largos |
| Juguetona | Display gruesa, sans amigable | Dos colores saturados que chocan a propósito | Formas de pegatina, sombras descentradas | Elástico con rebote exagerado |
Cada fila tiene un preset listo en assets/directions/ (fuentes, paleta clara y oscura con
contraste verificado, radio, sombra, movimiento) y una lista de movimientos característicos
en references/directions.md. Carga el preset después de tokens.css, usa al menos dos de
sus movimientos característicos y cambia sus matices hacia la marca. El minimalismo suizo es
el séptimo preset.
Reglas para la elección:
- Derívala del Paso 1, no del hábito. Un panel para ingenieros de SRE no es "lujoso".
- Nómbrala en tu respuesta ("Dirección: industrial / técnica") para que el usuario pueda redirigir temprano.
- Si el usuario pide algo insípido ("simple, limpio") , igualmente elige: "Minimalismo suizo" es una dirección (cuadrícula estricta, una grotesk, negro + un color, cero decoración).
Paso 3 - Define los tokens primero
Antes de escribir un solo componente, define tokens para: color, tipo, espaciado,
radio, sombra, movimiento, z-index. Comienza desde assets/tokens.css: conserva los nombres,
reemplaza los valores.
Los valores iniciales (Fraunces + Instrument Sans, neutros papel, acento bermellón)
son un marcador de posición, no un estilo. Antes de escribir componentes, cambia al menos
el par de fuentes (desde references/typography.md, emparejado con tu dirección), el
matiz del acento y el matiz hacia el que se tiñen los neutros. Por qué: en las pruebas, los
tokens iniciales sin cambios hicieron que un formulario de inicio de sesión y una página de
precios de productos no relacionados se vieran idénticos. Ese es un nuevo valor por defecto,
que es el problema que esta habilidad existe para solucionar. Consérvalos solo si la dirección
es realmente editorial cálida con un acento rojo anaranjado.
La forma más rápida de obtener una nueva paleta accesible: generarla, luego pegarla sobre los tokens de color en el bloque 2.
node scripts/palette.mjs --hue 250 --accent 130 --dark-first # neutros pizarra, acento lima
--hue tiñe los neutros (usa el matiz de la marca), --accent es el matiz del acento. Cada
par texto/fondo está resuelto para pasar WCAG AA en modo claro y oscuro antes de imprimirse.
Para direcciones oscuro-primero (paneles de monitoreo, herramientas de desarrollador, temas
nocturnos de lujo), establece :root { color-scheme: dark; } para que oscuro sea el valor
por defecto y claro sea opt-in.
Por qué: los tokens hacen que la dirección sea aplicable. Un #6366f1 o 13px codificados
en un componente son una decisión tomada de forma aislada, y veinte de esas hacen que la
interfaz se desvíe. Con tokens, el modo oscuro, los temas y los rediseños posteriores son
cambios de un solo archivo.
Reglas:
- Dos capas: paleta cruda (
--ink-900,--clay-500) y tokens semánticos (--color-text,--color-accent,--color-surface). Los componentes usan solo tokens semánticos. - Sin números mágicos en los componentes. Cada color, tamaño, espacio, radio, sombra,
duración y z-index proviene de un token. Excepciones:
0, líneas finas de1px,100%y1fr. - Modo oscuro: cada color semántico es
light-dark(CLARO, OSCURO), para que ambos temas vivan en una declaración y los componentes nunca cambien. Consultareferences/color-and-theming.md.
Tailwind: haz que los tokens sean el tema, para que existan bg-surface, text-text-muted,
font-display y rounded-md y no exista bg-indigo-500.
- v4: el segundo bloque en
assets/tokens.cssya usa los namespaces de Tailwind (--color-*,--font-*,--text-*,--radius-*,--shadow-*,--ease-*). Cambia el:rootde ese bloque a@themey añade--color-*: initial;como su primera línea para eliminar la paleta predeterminada. Mantén el bloque 3 (color-scheme) como CSS plano. Las utilidades resuelvenlight-dark()por tema, porque hacen referencia avar(--color-*). No escribas@theme inline { --color-x: var(--color-x) }; una variable que hace referencia a su propio nombre es un ciclo y no se resuelve a nada. - v3: en
tailwind.config, establecetheme.colors(noextend) a{ surface: "var(--color-surface)", ... }y extiendefontFamily,borderRadius,boxShadowde la misma manera.
Paso 4 - Construye mobile-first, con cada estado
Escribe estilos base para un viewport de 360px, luego añade consultas de medios min-width o
de contenedor. Por qué: es más fácil añadir espacio que quitarlo, y la mayoría de los errores
de maquetación (desplazamiento horizontal, tablas aplastadas) solo aparecen en anchos pequeños.
Cada elemento interactivo incluye todos sus estados. Los estados faltantes son la razón más común por la que una interfaz se siente inacabada.
| Estado | Qué debe mostrar |
|---|---|
| predeterminado | el diseño en reposo |
| hover | cambio sutil (color o sombra), solo bajo @media (hover: hover) |
| focus-visible | un anillo claramente visible, nunca eliminado |
| active | respuesta de presión (más oscuro, o translateY(1px)) |
| disabled | menor contraste + cursor: not-allowed, y el atributo disabled real |
| loading | spinner o skeleton, aria-busy="true", el ancho no salta |
| error | mensaje de texto cerca del campo, no solo un borde rojo |
| empty | un mensaje real y una siguiente acción, nunca un cuadro vacío |
Usa HTML semántico primero: <button> para acciones, <a href> para navegación,
<label for> para cada entrada, <dialog> para modales, <table> para datos
tabulares, puntos de referencia (<header> <nav> <main> <footer>). Añade ARIA solo cuando
HTML no tenga un equivalente nativo. Por qué: los elementos nativos vienen con comportamiento
de teclado y semántica de lector de pantalla gratis; ARIA es una promesa que luego tienes que implementar.
Escribe contenido real. El texto de marcador de posición ("Lorem ipsum", "Característica 1", "Juan Pérez") esconde problemas de maquetación y hace que el resultado parezca una plantilla. Usa contenido específico y verosímil que se ajuste al propósito del Paso 1.
Paso 5 - Audita antes de entregar
Ejecuta scripts/audit.md: bash scripts/audit.sh <archivos modificados> (verificaciones de patrón más
contraste de tokens), luego, si Playwright está disponible o el usuario acepta instalarlo,
node scripts/browser-check.mjs <página> y mira las capturas de pantalla que guarda. Arregla lo que falle. Las proporciones escritas
en los comentarios son afirmaciones, no mediciones; calcúlalas. No informes el trabajo como terminado con fallos conocidos; si algo no
se puede arreglar (por ejemplo, un color de marca que falla el contraste), dílo explícitamente.
Modo multi-agente (cuando una herramienta de subagente está disponible)
El agente principal siempre realiza los Pasos 0-4 por sí mismo: pensar y construir necesitan el mismo contexto, y dividirlos pierde lo que el Paso 0 encontró. Usa subagentes solo en dos puntos:
-
Propuestas de dirección (Paso 2, solo para briefs abiertos). Si no hay marca, captura de pantalla o sistema de diseño existente, lanza 2-3 subagentes en paralelo. Dale a cada uno las líneas del Paso 1 y asigna a cada uno una dirección diferente de la tabla. Dile a cada uno que lea primero su sección de
references/directions.mdyreferences/typography.md, y da a cada uno las direcciones de los otros agentes para que las eviten. Cada uno devuelve solo: dirección, par de fuentes, matiz de acento + neutro, diferenciador, dos movimientos característicos. Rechaza una propuesta que reutilice el par de fuentes, el matiz de acento o el diferenciador de otro, o que conserve los valores iniciales detokens.css. Elige una (o muestra las opciones al usuario), luego continúa solo. Por qué: un agente converge en el promedio; los puntos de partida forzados diferentes no lo hacen. Omite esto cuando la marca ya establece la dirección. -
Revisión independiente (Paso 5, siempre para nuevas páginas o pantallas). Después de que tu propia auditoría pase, lanza un subagente nuevo que no haya escrito el código. Dale los archivos modificados, las líneas del Paso 1 y la dirección elegida, y pídele que: lea
references/anti-patterns.md, ejecutescripts/audit.sh, y enumere cada lugar donde la interfaz se vea genérica, le falte un estado o rompa la dirección. Clasifica cada hallazgo como bloqueante / importante / menor y no edita. Arregla todos los bloqueantes e importantes, vuelve a ejecutarscripts/audit.sh, y enumera los menores no corregidos en la respuesta. Una ronda de revisión, sin bucle. Por qué: el constructor juzga el resultado por lo que pretendía hacer, no por lo que está en pantalla.
Sin herramienta de subagente: haz ambas pasadas tú mismo, en orden. Para la revisión, vuelve a leer los archivos como si alguien más los hubiera escrito.
Reglas de calidad (y por qué)
Tipografía
- No uses por defecto Inter, Roboto, Arial, Helvetica o system-ui para texto de display. Evita también los nuevos valores por defecto de IA: Poppins, Montserrat, Space Grotesk, DM Sans. Por qué: estos son los que usa cada página generada, así que señalan "generado".
- Combina una cara display con una cara de cuerpo que contraste en estructura (serif + sans, condensada + ancha, grotesk + mono). Dos familias como máximo, más una mono opcional.
- Usa una escala modular con tamaños fluidos (
clamp()), y haz que el título más grande sea dramáticamente más grande que el texto del cuerpo. La jerarquía tímida (32px sobre 16px) parece inacabada. - Texto del cuerpo: 16px como mínimo, altura de línea 1.5-1.7, medida 60-75 caracteres. Los panales densos pueden usar 12-14px para metadatos y celdas de tabla, nunca para párrafos o entradas.
Color
- Un color dominante lleva la marca; un acento nítido está reservado para la acción principal y los datos clave. Los neutros hacen la mayor parte del trabajo. Aproximadamente 60/30/10. Por qué: una paleta de cinco colores distribuida uniformemente no tiene punto focal, por lo que nada se lee como importante.
- Tiñe tus neutros hacia el matiz de la marca en lugar de usar gris puro.
- Sin degradados de púrpura a azul o púrpura sobre blanco a menos que la marca sea realmente púrpura.
- Contraste de texto de al menos 4.5:1 (3:1 para texto de 24px+ o 18.66px+ en negrita, y para límites de componentes de interfaz y anillos de enfoque).
Diseño y forma
- Evita la cuadrícula idéntica de tres o cuatro tarjetas. Varía el tamaño y el énfasis: un elemento destacado que abarca dos columnas, una lista junto a un elemento visual grande, una división asimétrica.
- El radio sigue la dirección y es consistente por nivel. No pongas
rounded-2xlen todo; los controles pequeños obtienen radio pequeño, o ninguno. - Sin desplazamiento horizontal a 320px. Usa
min-width: 0en hijos de flex/grid,overflow-wrap: anywherepara cadenas largas, y contenedores de desplazamiento para tablas anchas. - Objetivos táctiles de al menos 44x44px (el relleno cuenta).
Iconos e imágenes
- Sin emojis como iconos. Usa un conjunto de iconos (Lucide, Phosphor, Heroicons, Tabler) con un grosor de trazo, o SVG en línea. Por qué: los emojis se renderizan de manera diferente según el sistema operativo, no se pueden colorear con tokens, y los lectores de pantalla los anuncian ("cohete").
- Los iconos decorativos obtienen
aria-hidden="true"; los botones solo con icono obtienen unaaria-label.
Movimiento
- Anima solo
transformyopacity(másfiltercon moderación). Por qué: otras propiedades activan el diseño o la pintura en cada fotograma y tartamudean en teléfonos de gama baja. - Duraciones desde tokens: 120-200 ms para retroalimentación de la interfaz de usuario, 250-400 ms para elementos que entran.
- Respeta
prefers-reduced-motion: elimina el movimiento, mantén los fundidos cortos o instantáneos.
Accesibilidad - Asegúrate de que toda la interfaz sea navegable por teclado y compatible con lectores de pantalla siguiendo las pautas WCAG AA. Las etiquetas ARIA solo se usan cuando el HTML nativo no es suficiente, y todos los campos de formulario deben tener una etiqueta visible asociada.
Rendimiento - Optimiza las imágenes y los recursos; evita animaciones costosas y consultas excesivas al DOM. Usa content-visibility en secciones fuera de la pantalla para acelerar la carga inicial.