¿Qué hace preview-first?
Mira antes de construir. Esta habilidad inserta una etapa de diseño antes de escribir cualquier código de aplicación: el desarrollador ve varias direcciones de diseño completas y claramente diferentes en su navegador, elige una, y la elección se convierte en un contrato escrito que toda sesión posterior debe seguir.
Esto es una etapa de estudio de diseño, no un generador de sitios web. La habilidad nunca escribe el código de aplicación del desarrollador. Produce una decisión y un contrato. Los scripts son deterministas y usan la biblioteca estándar de Python; el juicio (leer el resumen, nombrar direcciones, redactar el copy) es suyo.
Cuándo ejecutarlo, cuándo ofrecerlo
Ejecute la etapa completa cuando el desarrollador esté a punto de iniciar, reiniciar o rediseñar un proyecto web: "construye una landing page para X", "inicia el frontend", "no me gusta cómo se ve esto", "elige colores y fuentes", o una llamada explícita /preview-first.
Ofrézcalo en una línea cuando el proyecto ya tenga código de UI pero no design/DESIGN.md: "¿Quieres ver primero las direcciones de diseño? Puedo mostrar el aspecto actual junto a alternativas". Si se acepta, importe el aspecto existente como una dirección (ver Importaciones) para que se compare en igualdad de condiciones.
Nunca lo active para ediciones pequeñas de una aplicación ya estilizada ("agrega un botón", "arregla el padding"). Cuando design/DESIGN.md exista, omita y pase a la fase posterior a la entrega.
El flujo
Todos los scripts residen en el directorio scripts/ de esta habilidad. Ejecútelos con python3 (o uv run python3 donde el proyecto use uv). Las rutas a continuación son relativas a la raíz del proyecto.
1. Lea el proyecto, luego haga como máximo cuatro preguntas
Lea lo que existe antes de preguntar nada: package.json, configuración de Tailwind, propiedades personalizadas de CSS, un logo SVG, fuentes existentes, un README. Todo lo encontrado es una restricción, no una pregunta.
Pregunte solo lo que el repositorio no pueda responder, en lenguaje llano, en un solo mensaje:
- ¿Cuál es el producto y para quién es, en una oración?
- Tres palabras sobre cómo debería sentirse, o un sitio que admiren.
- ¿Algo fijo? Un color de marca, un logo, una fuente, solo modo claro u oscuro.
- ¿Qué tipo de página importa más: marketing, aplicación, contenido o tienda?
2. Escriba el brief
Normalice las respuestas en .design-preview/brief.json:
{
"product": "Ledgerline, una herramienta de facturación para desarrolladores freelance",
"audience": "desarrolladores solitarios y estudios pequeños",
"product_type": "product-type.saas",
"moods": ["preciso", "tranquilo", "confiable"],
"page_type": "marketing",
"constraints": {"brand_colors": ["#154d8c"], "fonts": [], "scheme": "both"},
"admired": ["https://linear.app"],
"words": {"name": "Ledgerline", "tagline": "Facturas que coinciden con tu git log"}
}
Mapee el texto libre a IDs de nodos con recommend.py --list product-types y --list moods. Las palabras desconocidas están bien; el recomendador recurre a alias y superposición de tokens. El texto libre en product_type también se acepta.
3. Escriba el copy, luego abra la vista previa en menos de un minuto
Escriba .design-preview/copy.json primero; solo requiere una respuesta breve y es lo que hace que un borrador se lea como el producto en lugar de una plantilla. Use los propios sustantivos del producto: la navegación son sus secciones, las características son las cosas que hace, el titular es una afirmación que un usuario repetiría.
{
"headline": "Puntuaciones en vivo para 501, Cricket y Around the Clock",
"subhead": "Oche lleva la cuenta para que los jugadores puedan seguir jugando.",
"lead": "Hecho para jugadores de ligas de pub y amigos en casa.",
"cta_primary": "Nuevo juego", "cta_secondary": "Reanudar",
"nav": ["Juegos", "Jugadores", "Estadísticas", "Configuración"],
"features": [{"title": "501 y 301 con cuentas de salida", "body": "Cada puntuación restante muestra la ruta de salida estándar."}],
"proof": "", "meta": {"city": "Leeds", "year": "2026"},
"footer": "Oche lleva la cuenta."
}
Luego un comando:
python3 <skill>/scripts/quick_start.py --brief .design-preview/brief.json --copy .design-preview/copy.json --count 5 --open
Recomienda paquetes, escribe directions.json, construye la vista previa e inicia el servidor. Dé al desarrollador la URL de inmediato. Si omite --copy, los borradores usan copy derivado de los propios sustantivos del brief; nunca deje eso en una dirección que presente como terminada. Refine directions.json (nombres, justificación, diseño, programa) mientras miran, y reconstruya; la página se actualiza a la misma URL.
Cada página de vista previa lleva tres generadores en su barra, para que el desarrollador nunca tenga que volver atrás para obtener más: Sorpréndeme (una dirección compuesta aleatoriamente: un estilo no utilizado, una paleta y combinación adecuadas, un sorteo aleatorio de ideas, secciones y programa), Variaciones (cinco versiones de la dirección que están mirando: mismo estilo, otras paletas, combinaciones, ideas y programas) y, en la galería, Mostrar todos los estilos (una dirección por estilo para este brief). Cada uno aterriza en el nuevo borrador, que lleva los mismos botones. Desde el terminal: random_direction.py --directions .design-preview/directions.json --build .design-preview [--like B | --all].
3a. Paquetes candidatos manualmente
python3 <skill>/scripts/recommend.py --brief .design-preview/brief.json --count 4
Cada paquete es un estilo, paleta, combinación tipográfica, tratamientos de componentes, patrones de animación, conjunto de iconos y de ocho a doce ideas de diseño (ideas: movimientos seleccionados como una navegación dividida con hora en vivo, un héroe de espécimen, números gigantes, grano de película, botones de bracket, un pie de colofón), con los bordes del grafo que lo justificaron y alternativas en vivo para intercambiar. Se exige diversidad: familias de estilos distintas, como máximo dos paletas de una misma temperatura, como máximo dos combinaciones de una misma categoría tipográfica, ninguna paleta o combinación usada dos veces. Tres a cinco paquetes por defecto, hasta ocho cuando el desarrollador pida ver más. No baje de tres; si el brief es estrecho (solo modo oscuro, un color de marca), dígalo y aún así muestre tres.
4. Escriba directions.json
Convierta los paquetes en .design-preview/directions.json (esquema en knowledge/schema.json, files.directions). Para cada dirección, proporcione lo que un script no puede:
name: una idea, no un estilo ("Ledger", "Invernadero", "Turno nocturno"). Nunca "Moderno" o "Limpio".rationale: un párrafo que cite las propias palabras del brief y explique por qué esta dirección las responde. Mencione la única elección audaz y lo que permanece en calma.copy: copy real del brief: titular, subtítulo, dos llamadas a la acción, cuatro etiquetas de navegación, de tres a seis características con un título y una oración cada una, una línea de prueba honesta (o vacía), un título de formulario con etiquetas de campo y texto de envío, una línea de pie de página. En minúscula, voz activa, sustantivos del producto, sin guiones largos, sin emojis, sin flechas, sin "Ya seas X o Y", sin tricolones, sin lorem ipsum, sin números inventados. El copy es el mismo en todas las direcciones a menos que la voz de una dirección difiera genuinamente.layout(opcional): anula las variantes de sección; de lo contrario, las ideas de la dirección y luego los valores predeterminados del estilo las eligen.bundle.ideas(conservar o editar): las ideas que el recomendador adjuntó. Elimine una que no encaje con el producto, agregue una derecommend.py --list ideascuando el brief o un sitio admirado lo solicite. Las ideas con un hook de renderizado cambian el borrador; el resto van al contrato.copy.numbersycopy.stats(opcional): cifras con fuente{value, label, source}; el héroe de números y el muro de estadísticas se renderizan solo cuando existen, nunca con cifras inventadas.copy.meta(opcional):{"city": "Lisboa"}para la navegación dividida, el colofón y el reloj superpuesto.- El tipo de producto lleva un kit temático (tipos de obra de arte, un componente temático como un terminal, un balance, un horario, un compositor, un marcador y los sustantivos del producto). La primera pantalla y la sección siguiente lo usan, de modo que un marcador se abre con una puntuación y una tienda con productos. Establezca
layout.topicanonepara eliminar el componente temático. overrides(opcional):{"brand_primary": "#hex", "brand_accent": "#hex"}cuando el brief fija un color de marca. El constructor recalcula los colores sobre el fondo e informa cualquier fallo de contraste.
Antes de construir, ejecute la verificación anti-obviedad en references/anti-patterns.md en cada dirección. Rechace una obviedad a menos que el brief la haya solicitado por su nombre, y dígalo en la justificación.
La regla de la primera pantalla: ninguna dirección se abre con la plantilla genérica (titular centrado, dos botones, una captura de pantalla, luego tres tarjetas idénticas). Cada estilo usa por defecto un arquetipo de diseño observado en sitios admirados (párrafo de declaración con figuras subtituladas, tipografía envolviendo un disco plano, escenario primero el producto, fuente display junto a un objeto, obra de arte a sangre completa, índice lateral, tipo de póster) y una obra de arte generada a partir de la paleta (plano, figuras isométricas, terminal, composición suiza, contornos, medios tonos, anillos orbitales, pegatinas, gráficos de líneas, una sola marca). Mantenga esos valores predeterminados a menos que el brief solicite el aspecto familiar por su nombre. Al menos dos de las direcciones provienen de estilos marcados como distinct; el recomendador lo exige, y también se asegura de que dos direcciones no compartan un dispositivo de navegación, un dispositivo de primera pantalla o una textura.
5. Construya y abra la vista previa
python3 <skill>/scripts/build_preview.py --directions .design-preview/directions.json
python3 <skill>/scripts/serve_preview.py --dir .design-preview --open
build_preview.py escribe .design-preview/: una galería, y para cada dirección un mosaico de estilo (paleta con grados de contraste en ambos modos, escala tipográfica, espaciado, radio, elevación, iconos, cada componente en todos los estados, patrones de animación reproducibles), una página borrador para el tipo de página del brief, y una vista de dispositivos que renderiza el borrador dentro de marcos dibujados con CSS de los teléfonos, plegables, tabletas y laptops más populares en tamaños de ventana reales. Los controles en cada página permiten intercambiar paleta, combinación tipográfica, radio, densidad, nivel de animación y tema en vivo.
serve_preview.py inicia un servidor localhost separado, escribe .design-preview/server.json, imprime la URL y regresa inmediatamente. Agregue --vendor-fonts a la compilación para una sesión sin conexión; de lo contrario, el mosaico muestra un aviso visible cuando una fuente web no se cargó.
Si el navegador no se puede abrir (SSH, contenedor, CI), imprima la URL y la lista de direcciones con una línea cada una, y continúe en el chat.
6. Informe al desarrollador, luego espere
Diga lo que construyó, dé la URL, nombre las direcciones en una línea cada una, y deténgase. No elija por ellos, no comience a codificar, no sondee. El desarrollador puede pasar mucho tiempo en la vista previa. Cuando respondan:
- Si
.design-preview/selection.jsonexiste, léalo. Contiene el ID de la dirección y las anulaciones en vivo (paleta, combinación, radio, densidad, animación, tema) en las que se quedaron. - De lo contrario, tome la elección de sus palabras ("B", "la oscura", "A pero con el tipo de D") y escriba
selection.jsonusted mismo con las anulaciones correspondientes. - Para una mutación ("B pero más cálida", "menos bordes redondeados", "cambia la fuente del titular"), edite
directions.json(o use una alternativa del paquete), reconstruya y vuelva a señalar a la misma URL. El servidor sigue ejecutándose; pida que actualicen la página. - Para "muéstrame más", ejecute
recommend.pyde nuevo con--count 5o un brief modificado, agregue las nuevas direcciones con nuevos ID y reconstruya.
serve_preview.py --dir .design-preview --wait 1800 bloquea hasta que exista una selección, solo para uso scripteado. --status y --stop gestionan el servidor.
7. Exporte el contrato
python3 <skill>/scripts/export_design.py --selection .design-preview/selection.json \
--directions .design-preview/directions.json --project .
Esto escribe design/DESIGN.md (el contrato: identidad, ideas de diseño con fuentes y notas de compilación, paleta con tabla de contraste, tipografía, espaciado y radio, elevación, diseño, cada componente con estados y tokens, tokens de animación y patrones permitidos, iconografía, imaginería, estilo de escritura, nivel mínimo de accesibilidad, verificaciones de dispositivo, y una lista de "no hacer"), design/tokens.json (formato W3C Design Tokens), design/tokens.css, design/tailwind.css cuando se detecte Tailwind v4, una línea de puntero en CLAUDE.md, y una entrada .gitignore para .design-preview/. La reexportación conserva la sección "Project notes" y copia los archivos anteriores a design/history/.
Confirme en un mensaje corto qué se escribió y qué debe confirmar el desarrollador (design/ y la línea de CLAUDE.md). Luego construya bajo el contrato.
Posterior a la entrega
Siempre que design/DESIGN.md exista:
- Léalo antes de cualquier cambio de UI. Use tokens
--pf-*dedesign/tokens.css, nunca valores hex, pixel o milisegundo sin procesar en los componentes. - Respete los patrones de animación permitidos y el nivel de animación. Respete la reducción de movimiento.
- Ejecute
contrast.py FG BG --role body|label|large|uien cada nuevo par de colores. - Siga la lista de "no hacer"; cuando una solicitud entre en conflicto con el contrato, dígalo y ofrezca volver a ejecutar la etapa en lugar de desviarse silenciosamente.
- Después de construir una página significativa, ofrezca la verificación de dispositivos: abra
.design-preview/<id>/dispositivos.html?url=http://localhost:PORT/rutapara ver la página real en los mismos marcos. Las páginas que envían encabezados de bloqueo de marcos no se pueden mostrar; dígalo. - Mantenga las secciones libres de
design/DESIGN.md(debajo del marcador de fin) para decisiones del proyecto.
Importaciones
Para comparar el aspecto actual del proyecto, o un sitio que el desarrollador admira, como una dirección:
python3 <skill>/scripts/import_direction.py --css src/styles.css --into .design-preview/directions.json --name "Hoy"
python3 <skill>/scripts/import_direction.py --tailwind tailwind.config.js --into .design-preview/directions.json
python3 <skill>/scripts/import_direction.py --tokens design-tokens.json --into .design-preview/directions.json
python3 <skill>/scripts/import_direction.py --url https://example.com --into .design-preview/directions.json --name "Referencia"
La importación deriva una paleta, combinación y estilo más cercano, luego reconstruye. Las paletas importadas se verifican como cualquier otra; los fallos aparecen en el mosaico.
Conocimiento y actualización
Las decisiones provienen de knowledge/graph.json: estilos, paletas (OKLCH, ambos modos), combinaciones tipográficas, tratamientos de componentes, patrones de animación, tipos de producto, estados de ánimo, conjuntos de iconos, características de plataforma, sitios de referencia, unidos por pairs_with, suits, avoid_with, requires, ex.
…
[truncado para traducción]