Playwright. Abre la página en un navegador de verdad y le cuenta qué ha salido. Va primero porque sin esto las otras tres son a ciegas.
playwrightClaude diseña webs a ciegas. Escribe el HTML, escribe el CSS, y nunca ve el resultado. Por eso salen con olor a plantilla: no es que tenga mal gusto, es que trabaja sin mirar.
Esta guía monta las cuatro piezas que lo arreglan, en el orden que importa. Y empieza por el final, que es lo interesante: los ojos van primero.
01 el problema
Piensa en cómo trabajas tú cuando maquetas algo. Escribes una regla, miras, ajustas. Miras otra vez. Ese bucle —escribir, mirar, corregir— es el noventa por ciento del trabajo, y es exactamente el que Claude no puede hacer.
Sin ojos solo le queda una estrategia: escribir lo que estadísticamente suele funcionar. De ahí sale el aspecto reconocible que todo el mundo identifica ya: la tipografía por defecto, el degradado de moda, las tarjetas con la misma sombra, el mismo espaciado en todo.
Al montar la web que estás leyendo, los botones salían con el icono encima del texto en vez de al lado, y las etiquetas de cada entrada ocupaban toda la línea en vez de ir en píldoras. En el código no había nada raro: las clases eran correctas y las reglas también.
La causa era que una segunda hoja de estilos se cargaba después y ganaba por orden de cascada. Eso no se ve leyendo, porque los dos archivos por separado están bien. Se vio al renderizar la página y medir los estilos calculados: el botón resolvía display:block cuando su regla decía inline-flex.
Ése es el trabajo que hacen los ojos, y es el motivo de que Playwright vaya primero y no último.
Un fallo de diseño casi nunca es «el código está mal». Suele ser «el código está
bien y el resultado no es el que dice el código». Sin renderizar, esa diferencia
es invisible.
02 el método
Las cuatro piezas se pueden instalar en cualquier orden y todas funcionan. Pero el orden en que las instales decide cómo trabaja Claude, y eso sí cambia el resultado.
Playwright. Abre la página en un navegador de verdad y le cuenta qué ha salido. Va primero porque sin esto las otras tres son a ciegas.
playwrightEl MCP de shadcn. Botones, formularios y tarjetas con el código que tú usarías.
shadcn mcpEl MCP de Magic UI. Animaciones y transiciones. Lo que hace que apetezca mirarla.
magicui mcpLa skill frontend-design de Anthropic. Jerarquía, espaciado, tipografía.
frontend-designSin el cuatro, los tres primeros son piezas caras mal colocadas. Sin el uno, los otros tres son a ciegas. Ese es todo el argumento del orden.
03 los ojos
Playwright es una herramienta de automatización de navegador. Abre tu página en Chromium, Firefox o WebKit de verdad —no en una simulación— y puede leer cualquier cosa de ella: posiciones, tamaños, colores calculados, si algo desborda.
Hay dos formas de usarlo con Claude y conviene entender la diferencia.
Es la que yo uso y la que menos falla. Un archivo corto que abre la página, mide lo que te interesa e imprime números.
import { chromium } from '@playwright/test'
const URL = process.argv[2] ?? 'http://localhost:3000'
const ANCHO = Number(process.argv[3] ?? 390)
const nav = await chromium.launch()
const ctx = await nav.newContext({ viewport: { width: ANCHO, height: 844 } })
const p = await ctx.newPage()
await p.goto(URL, { waitUntil: 'domcontentloaded' })
await p.waitForSelector('main, body > *')
const d = await p.evaluate(() => {
const cs = e => getComputedStyle(e)
const visible = e => {
const r = e.getBoundingClientRect()
return r.width > 0 && r.height > 0 && cs(e).visibility !== 'hidden'
}
// ── color: rgb(a) -> [r,g,b,a] ────────────────────────────────────────────
const rgba = s => (s.match(/[\d.]+/g) || [0, 0, 0, 0]).map(Number)
// Pinta `frente` (que puede llevar alfa) encima de `detras`.
const mezcla = (frente, detras) => {
const a = frente[3] === undefined ? 1 : frente[3]
return [0, 1, 2].map(i => Math.round(frente[i] * a + detras[i] * (1 - a)))
}
// El fondo REAL. getComputedStyle devuelve rgba(0,0,0,0) cuando es
// transparente, que es el caso normal, así que hay que subir por los
// ancestros. Pero NO basta con quedarse con el primero que tenga alfa:
// una capa a rgba(15,12,8,0.04) sobre blanco es casi blanca, y tratarla
// como negra da ratio 1,0 sobre texto perfectamente legible. Se apilan
// las translúcidas y se componen sobre el primer opaco.
const fondo = e => {
const capas = []
let base = [255, 255, 255]
for (let n = e; n; n = n.parentElement) {
const c = rgba(cs(n).backgroundColor)
const a = c[3] === undefined ? 1 : c[3]
if (a === 0) continue
if (a === 1) { base = c.slice(0, 3); break }
capas.push(c)
}
return capas.reverse().reduce((acc, c) => mezcla(c, acc), base)
}
// Luminancia relativa y ratio, según WCAG 2.2
const lum = ([r, g, b]) => {
const f = v => (v /= 255) <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4
return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b)
}
const ratio = (a, b) => {
const [x, y] = [lum(a), lum(b)].sort((m, n) => n - m)
return (x + 0.05) / (y + 0.05)
}
// ── 1 · ¿se sale la página por el lado? ───────────────────────────────────
const desborda = document.documentElement.scrollWidth
- document.documentElement.clientWidth
// ── 2 · objetivos pulsables por debajo de 44 px en el lado corto ──────────
const pulsables = [...document.querySelectorAll(
'a, button, [role="button"], input, select, textarea, summary')]
.filter(visible)
.map(e => ({ e, r: e.getBoundingClientRect() }))
.filter(({ r }) => Math.min(r.width, r.height) < 44)
.map(({ e, r }) => ({
que: e.tagName.toLowerCase() + (e.className ? '.' + String(e.className).split(' ')[0] : ''),
texto: (e.textContent || '').trim().slice(0, 24),
w: Math.round(r.width), h: Math.round(r.height),
}))
// ── 3 · contraste del texto contra su fondo ───────────────────────────────
const bajos = []
for (const e of document.querySelectorAll('p, li, a, span, h1, h2, h3, td, th, button')) {
if (!visible(e)) continue
const propio = [...e.childNodes].some(n => n.nodeType === 3 && n.textContent.trim())
if (!propio) continue
const est = cs(e)
const px = parseFloat(est.fontSize)
const grande = px >= 24 || (px >= 18.66 && Number(est.fontWeight) >= 700)
const min = grande ? 3 : 4.5
const bg = fondo(e)
const r = ratio(mezcla(rgba(est.color), bg), bg)
if (r < min) bajos.push({
que: e.tagName.toLowerCase(), texto: (e.textContent || '').trim().slice(0, 24),
ratio: Number(r.toFixed(2)), exige: min,
})
}
// ── 4 · caracteres por línea ──────────────────────────────────────────────
const anchos = []
for (const e of document.querySelectorAll('p, li')) {
if (!visible(e)) continue
const t = (e.textContent || '').trim()
if (t.length < 40) continue
const r = e.getBoundingClientRect()
const alto = parseFloat(cs(e).lineHeight) || parseFloat(cs(e).fontSize) * 1.2
const lineas = Math.max(1, Math.round(r.height / alto))
const cpl = Math.round(t.length / lineas)
if (cpl > 70) anchos.push({ cpl, texto: t.slice(0, 30) })
}
return {
desborda,
pulsables_pequenos: pulsables.length, pulsables,
contraste_bajo: bajos.length, bajos,
lineas_largas: anchos.length, anchos,
}
})
// Un informe corto y pegable, no un volcado: si la salida no cabe en la
// pantalla, nadie la lee y el bucle deja de tener freno.
const linea = (rotulo, n, ok) => `${ok ? '✓' : '✗'} ${rotulo.padEnd(26)} ${n}`
console.log(`── ${URL} @${ANCHO}px ─────────────────────`)
console.log(linea('desborda a lo ancho', d.desborda + 'px', d.desborda === 0))
console.log(linea('pulsables < 44px', d.pulsables_pequenos, d.pulsables_pequenos === 0))
for (const x of d.pulsables.slice(0, 3)) console.log(` ${x.que} ${x.w}×${x.h} «${x.texto}»`)
console.log(linea('contraste bajo', d.contraste_bajo, d.contraste_bajo === 0))
for (const x of d.bajos.slice(0, 3)) console.log(` ${x.ratio}:1 exige ${x.exige} «${x.texto}»`)
console.log(linea('líneas > 70 caracteres', d.lineas_largas, d.lineas_largas === 0))
for (const x of d.anchos.slice(0, 3)) console.log(` ${x.cpl} car «${x.texto}»`)
await p.screenshot({ path: 'pantalla.png', fullPage: true })
await nav.close()Se lo das a Claude y le pides que lo ejecute y lea la salida. La captura, además, la puede mirar.
npm install -D @playwright/test instala la librería, y nada más: no trae navegadornpx playwright install chromium baja el navegador. Unos 130 MB la primera vez y ya no se vuelve a tocarSi prefieres no descargar nada y ya tienes Google Chrome instalado, cambia chromium.launch() por chromium.launch({ channel: 'chrome' }) y usa el que tienes. Pero que quede claro lo que exige: Chrome, no vale Chromium ni Brave, y en WSL —que es lo que recomiendo a quien va con Windows— normalmente no hay ninguno de los dos. Por eso el script de arriba no trae channel: la versión que funciona en más máquinas es la que se baja su propio navegador.
npm install -D @playwright/test && npx playwright install chromium
node medir.mjs http://localhost:3000 390Y esto es lo que imprime. No es un ejemplo inventado: es la salida de apuntarlo a la portada de esta misma bitácora el 31/08/2026, con sus fallos dentro.
── https://javivillegas-ai.cp.c2developers.com/bitacora/ @390px ─────────────────────
✓ desborda a lo ancho 0px
✗ pulsables < 44px 21
input.buscador 185×21 «»
a.pil 57×36 «Todo»
a.pil 54×36 «guia»
✗ contraste bajo 2
4.4:1 exige 4.5 «.»
4.4:1 exige 4.5 «javiergarcia@c2developer»
✓ líneas > 70 caracteres 0Veintiuno y dos. En mi propia web, publicada, después de mirarla mucho. Ése es justo el argumento de la guía: a ojo no se ve, y con números aparece en dos segundos.
La primera versión de este medidor subía por los ancestros hasta encontrar un fondo opaco y se quedaba con el primero que tuviera algo de color. Con una capa a rgba(15,12,8,0.04) —un tinte del 4 % sobre blanco— la trataba como casi negra, y reportaba 1,0:1 sobre un texto que se lee perfectamente.
Un medidor que da falsos positivos es peor que no tenerlo: mandas a Claude a arreglar algo que no está roto. Por eso fondo() compone las capas translúcidas en vez de quedarse con una, y el color del texto también se compone sobre el resultado, porque también puede llevar alfa.
Microsoft publica un servidor MCP oficial de Playwright que le da a Claude control del navegador directamente, leyendo la página como árbol de accesibilidad en vez de por capturas. Es más cómodo para explorar y navegar.
claude mcp add playwright -- npx -y @playwright/mcp@latestCuál usar: el MCP para explorar y hacer clic; el script para medir. Un
script que imprime números es reproducible y lo puedes meter en un examen
automático. Una sesión de navegador conversacional, no.
Node resuelve los paquetes desde la ruta del archivo, no desde donde lo ejecutas. Un script de Playwright guardado en /tmp no encuentra la librería aunque la tengas instalada, y el error no lo dice claro.
Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@playwright/test'
imported from /tmp/medir.mjsEl script vive dentro del proyecto. Siempre.
04 los ladrillos
Botones, formularios, tarjetas, diálogos. Claude los pide, se los instala él solo, y salen con el código que tú ya usarías: no una librería que importas, sino archivos que entran en tu proyecto y que puedes editar.
El MCP no es un paquete aparte: viene dentro de la propia herramienta de línea de comandos. Esto conviene saberlo porque hay forks de la comunidad que aparecen antes en las búsquedas.
npx shadcn@latest mcp init --client claudeSin el MCP, le pides un botón y te escribe un botón: HTML y CSS inventados sobre la marcha, que se parecen a los del proyecto pero no son los del proyecto. Con el MCP, busca en el registro, instala el componente real y lo usa.
La diferencia se nota a la tercera pantalla, cuando todos los botones son el mismo botón en vez de cinco primos lejanos.
Necesito una pantalla de alta de cliente. Antes de escribir nada: 1. Lista qué componentes hay disponibles en el registro para formularios. 2. Dime cuáles vas a usar y por qué ésos. 3. Instálalos. Y después móntala. No escribas ningún componente a mano si existe en el registro: quiero que todos vengan del mismo sitio, para que en la pantalla siguiente sean idénticos.
La última frase es la que evita el problema real. Sin ella mezcla componentes instalados con componentes escritos a mano y a las tres pantallas tienes dos sistemas de diseño conviviendo.
05 el movimiento
Magic UI pone lo que se mueve: animaciones, degradados, transiciones. Es la diferencia entre una web que funciona y una que apetece mirar. Está pensada como complemento de shadcn, así que las dos conviven sin pelearse.
npx shadcn@latest add "https://magicui.design/r/shimmer-button"Y su servidor MCP, que hace los componentes buscables desde el editor:
claude mcp add magicui -- npx -y @magicuidesign/mcp@latestÉsta es la pieza más floja de las cuatro y hay que decirlo. Comprobado el
31/08/2026: la librería está viva, pero su servidor MCP llevaba meses sin un
solo cambio y sin publicar versión nueva. Funciona, pero no está en desarrollo
activo. Si te falla, usa la librería directamente sin el MCP — se pierde la
comodidad de buscar desde el editor, no los componentes.
Casi siempre, menos del que apetece poner. Tres reglas que aplico:
gana el movimiento.
prefers-reduced-motion. Hay gente a la que el movimiento leprovoca mareo, y desactivarlo son tres líneas.
Añade esto a las instrucciones del proyecto: - Como mucho UN elemento animado por pantalla, y es el que dirige la mirada. - Nada en bucle infinito a menos de 200px de un bloque de texto largo. - Todo lo que se mueva va dentro de una consulta que respete prefers-reduced-motion: reduce, sin excepciones. - Las transiciones de interfaz, por debajo de 200ms. Por encima se percibe como lentitud, no como elegancia.
06 el criterio
Y debajo de todo va frontend-design, una skill publicada por Anthropic. Le pone criterio: jerarquía, espaciado, tipografía, cuándo una decisión visual es intencionada y cuándo es la de siempre.
Las skills son carpetas con instrucciones que Claude carga cuando le hacen falta.
git clone --depth 1 https://github.com/anthropics/skills.git /tmp/sk && cp -r /tmp/sk/skills/frontend-design ~/.claude/skills/ls ~/.claude/skills/frontend-designLas otras tres te dan material. Ésta te da criterio sobre el material, y es la diferencia entre una página con componentes buenos y una página bien compuesta.
En concreto es la que hace que no salga el aspecto genérico: te empuja a elegir una paleta que venga del tema, a emparejar dos tipografías con intención, y a que la estructura de la página diga algo sobre el contenido en vez de ser la retícula por defecto.
Componentes correctos, animaciones bonitas, y una página que se parece a otras cincuenta. Nada está mal y nada es memorable.
Las mismas piezas, colocadas con una intención que se puede explicar. Se nota sobre todo en el espaciado y en la tipografía, que es donde vive el oficio.
Una nota sobre licencias, porque se generaliza y no toca: en ese repositorio la
licencia va por skill, no en la raíz. frontend-design es Apache-2.0. Otras
del mismo repositorio no son código abierto. Si esto va a una empresa,
compruébalo skill a skill.
07 manos a la obra
Instala Playwright en el proyecto y escribe el medidor. Compruébalo ejecutándolo contra tu página: si imprime números, ya tienes ojos.
Arranca el MCP de shadcn. Comprueba pidiéndole que liste los componentes disponibles: si te los enumera, está conectado.
Añade Magic UI. Si el MCP no responde, sigue con la librería directamente y no pierdas la tarde: es la pieza más prescindible de las cuatro.
Copia la skill a tu carpeta de Claude y comprueba con ls que está. Sin comprobarlo no hay error: simplemente no se carga y tú no te enteras.
Pídele una pantalla y NO le digas qué está mal. Que la escriba, la abra, la mida y la corrija solo. Si hace ese bucle sin ti, el montaje está bien.
claude mcp listAquí hay una arruga que despista, y prefiero avisarte antes de que la veas. Los tres no salen en la misma lista. Los dos que has añadido con claude mcp add van a tu ámbito de usuario y aparecen siempre. El de shadcn no: shadcn mcp init --client claude escribe en el .mcp.json del proyecto, y los servidores de proyecto Claude Code te los pregunta al arrancar la sesión en esa carpeta antes de conectarlos.
Así que si shadcn no aparece, mira dos cosas antes de tocar nada: que estás ejecutando el comando dentro de la carpeta del proyecto, y que aceptaste el aviso de aprobación cuando abriste la sesión. No es que esté mal instalado, es que vive en otro sitio.
No te copio aquí la salida
La lista depende de lo que tengas montado tú, y he decidido que en esta bitácora
no se publica ninguna salida de terminal que yo no haya ejecutado. Escribir
tres palomitas de memoria es exactamente la forma de que alguien dé por buena
una instalación rota. Lo que tienes que ver es tu propia lista con playwright
y magicui conectados; shadcn, por lo de arriba, puede que no esté ahí.
08 cómo se usa
Con las cuatro montadas, el trabajo cambia de forma. Ya no le dices «el botón está pegado al borde». Él escribe, abre la página, ve que el botón está pegado al borde y lo mueve. Y repite hasta que aquello se ve bien.
Monta la pantalla que te he descrito. Y después, sin que yo te diga nada: 1. Abre la página con el medidor de Playwright a 390 y a 1440. 2. Comprueba, con números y no de vista: - que la página no desborda a lo ancho en ninguno de los dos tamaños - que ningún objetivo pulsable baja de 44px en el lado corto - que el texto principal contrasta 4,5:1 o más contra su fondo - que ningún bloque de texto pasa de 70 caracteres por línea 3. Si algo falla, arréglalo y vuelve a medir. **Máximo tres pasadas.** Si a la tercera queda algún número sin cumplir, PARA y dime cuál es, qué valor da y qué has intentado. No sigas dando vueltas. 4. Cuando esté, enséñame la captura y la tabla de medidas. No me cuentes lo que has hecho: enséñame los números. Si algo no se puede medir con el script, dímelo en vez de darlo por bueno.
Porque «ya está arreglado» no es una comprobación. Lo he visto fallar de las dos maneras: dar por corregido algo que no lo estaba, y corregir una cosa rompiendo otra que ya no volvió a mirar. Pedir la tabla de medidas cierra las dos puertas.
| Qué se mide | Umbral | De dónde sale | Qué caza |
|---|---|---|---|
| Desbordamiento horizontal | 0 px | No hay norma: o desborda o no | El fallo más común en móvil |
| Objetivo pulsable | 44 px de lado | Apple, guías de interfaz humana | Botones e iconos demasiado pequeños |
| Contraste de texto | 4,5:1 | WCAG 2.2, nivel AA | Gris sobre gris, que se ve bien en tu pantalla |
| Ancho de línea | 70 caracteres | Tipografía clásica, no una norma | Párrafos imposibles de leer en escritorio |
Los umbrales llevan fuente a propósito, porque dos de los cuatro son una elección mía y conviene que lo sepas. Los 44 px son de Apple; Android pide 48 y WCAG solo los exige en nivel AAA —su AA de la 2.2 se conforma con 24×24—. Y los 70 caracteres no son de ninguna norma: son tipografía de toda la vida. El único que es una regla de accesibilidad de verdad, y el que yo no negociaría, es el 4,5:1.
Con esas cuatro y el bucle corriendo solo, el noventa por ciento de lo que se enseña en una revisión de diseño ya está resuelto antes de que tú mires.
09 honestidad
El gusto no se instala. Estas cuatro piezas evitan los fallos y dan coherencia. No van a producir una identidad visual que emocione a nadie. Eso sigue siendo trabajo de diseñador, y decir lo contrario sería vender humo.
El contraste sobre una imagen no se puede medir así. El medidor lee el color de fondo declarado y compone las capas translúcidas, y con eso acierta en fondos planos. Pero si el texto va encima de una foto, de un degradado o de un vídeo, no hay color de fondo que leer: el número que salga no significa nada. Ahí se mira a ojo, y con el peor fotograma de la imagen, no con el mejor.
Los estilos calculados no lo cuentan todo. Un :hover no se dispara solo, y el foco por tabulación tampoco. Lo que está declarado se puede leer; lo que solo existe mientras interactúas, hay que provocarlo a propósito.
La zona segura del móvil no se puede medir en un navegador sin cabeza. El espacio del indicador de inicio del iPhone resuelve a cero, y ahí no se puede distinguir «funciona» de «vale cero». Eso hay que mirarlo en un teléfono real, y no hay vuelta.
La tipografía real cambia por plataforma. Lo que mides con la fuente del sistema en un equipo no es lo que verá alguien en otro. Los anchos de texto medidos son orientativos, no exactos.
Si una guía te promete que con esto ya no necesitas mirar la web en un móvil de
verdad, esa guía no ha probado nada en un móvil de verdad.
10 qué esperar
Enseguida: desaparecen los fallos tontos. Nada desborda, los botones se pueden pulsar, el contraste se cumple. Eso se nota en la primera pantalla.
A los pocos días: la coherencia. Como los componentes salen del mismo sitio, la tercera pantalla se parece a la primera sin que nadie lo haya vigilado.
Nunca: la sorpresa. Una web montada así queda correcta, limpia y sin errores. Para que además tenga personalidad hace falta una decisión que ninguna de las cuatro herramientas va a tomar por ti: elegir una dirección y sostenerla aunque sea incómoda.
Y ahí, otra vez, la ventaja es tener escrito por qué elegiste lo que elegiste. Lo cual es exactamente lo que monta la guía hermana de esta bitácora.
11 el catálogo
Esto no es teoría: son los que aparecen una y otra vez, con el motivo por el que son invisibles leyendo el código.
El más común con diferencia. Una tabla, un bloque de comando o una imagen que no cabe empuja el documento entero y aparece una barra horizontal que nadie quiere.
Por qué no se ve leyendo: el elemento culpable no tiene nada raro. El problema es la suma, y la suma solo existe al renderizar.
Cómo se arregla mal: poniendo overflow-x:hidden en el cuerpo. Eso no lo arregla, lo esconde: el contenido se sigue saliendo, solo que ya no se ve ni se puede alcanzar. Un desbordamiento invisible es peor que uno visible, porque nadie lo reporta.
Cómo se arregla bien: el scroll va en el contenedor acotado, y el hijo lleva width:max-content para tener qué arrastrar.
Cuando algo no quepa a lo ancho —una tabla, un bloque de código, un diagrama—: - El contenedor lleva overflow-x:auto y min-width:0. - El hijo lleva width:max-content y min-width:100%. - NUNCA overflow-x:hidden en html, body ni en el contenedor de la página. Y compruébalo con dos números, no de vista: - que el CONTENEDOR desborda por dentro (scrollWidth > clientWidth) - que la PÁGINA no desborda (documentElement.scrollWidth === clientWidth) Si solo compruebas el segundo, esconder el problema pasa el examen.
Un icono de 44 de alto y 29 de ancho pasa cualquier revisión que solo mire una dimensión. Se mide el lado corto, siempre.
svg sin tamaño se come a su padreUn <svg> sin width ni height se estira hasta el tamaño del contenedor. En una tarjeta puede ocupar doscientos píxeles y no da ningún error. Todo icono lleva tamaño, sin excepción.
Se ve perfectamente en tu pantalla buena, en una habitación con buena luz. No se ve en un móvil al sol. Por eso el contraste se mide con un número y no con la vista: 4,5:1 para texto normal, 3:1 para texto grande y para gráficos que significan algo.
La que me tocó a mí. Dos archivos de CSS correctos por separado, cargados en un orden que hace que uno pise al otro. El código está bien y el resultado está mal, que es la definición exacta de lo que solo se ve renderizando.
Un componente diseñado para llevar su contenido dentro de un elemento concreto, usado sin ese elemento. Las clases están, la regla está, y el color no aplica porque vive un nivel más abajo. Es el fallo más frustrante porque el código parece correcto y lo es: lo que está mal es el marcado, no el estilo.
Los seis tienen algo en común: ninguno produce un error. La página carga, la
consola está limpia y todo parece bien. Por eso hace falta medir, y por eso los
ojos van primero.
12 el criterio propio
La skill de Anthropic pone criterio general. Lo que no puede poner es tu criterio: tus colores, tu tipografía, tus decisiones. Eso va en las instrucciones del proyecto, y hay una forma de escribirlas que funciona y otra que no.
Veinte reglas de estilo, muchas de gusto y algunas contradictorias entre sí. Se cumplen las tres primeras y las demás se diluyen sin que nadie avise.
Cuatro o cinco reglas, cada una con su POR QUÉ y con un número cuando se pueda. Un número no se interpreta.
## Diseño Cada regla lleva su motivo. Si una regla choca con otra, gana la que esté antes en esta lista. 1. UN SOLO acento por pantalla. El acento es <tu color>. Si aparece dos veces compitiendo, deja de señalar y pasa a decorar. 2. La prosa se lee a 65 caracteres por línea como máximo. En una columna ancha, el texto se estrecha DENTRO; no se ensancha la columna. 3. Los radios son tres y solo tres: 6px campos y botones, 8px tarjetas, 12px contenedores grandes. Cualquier otro valor es un descuido. 4. El anillo de 1px va como box-shadow, no como border. Un border cambia la caja y desplaza el contenido; un box-shadow no. 5. Nada se declara solo dentro de una consulta de medios ni de un tema. Todo color se define primero en la raíz y se REDEFINE después. Un color que solo existe en modo oscuro deja la página ilegible en claro, y no da ningún error. Antes de dar una pantalla por terminada, mídela y enséñame los números.
Es la que produce el fallo más caro y menos evidente: una página que se ve perfecta en tu equipo y completamente ilegible en el de otro, porque el color del texto solo estaba definido en un tema y el fondo en el otro.
La comprobación es de diez segundos: busca en tu hoja cualquier color cuya única definición esté dentro de un bloque de tema o de una consulta de medios. Si hay alguno, ése es tu próximo error.
13 dudas
No. Playwright y la skill de criterio son las dos que cambian el resultado; las otras dos son comodidad. Si solo vas a poner dos, pon ésas.
Playwright y la skill, sí: son agnósticas. shadcn y Magic UI están hechos para React con Tailwind. Con otro montaje, el bucle de medir y corregir funciona exactamente igual; lo que cambia es de dónde salen los componentes.
Es donde más rinde. Apunta el medidor a tu web actual a 390 y a 1440 y mira los cuatro números. Casi nadie pasa los cuatro a la primera, y las correcciones suelen ser pequeñas.
Solo si se lo pides así. En el prompt del bucle, la instrucción de enseñar la tabla antes de dar nada por bueno es la que mantiene el control. Un bucle que corrige solo necesita un punto donde te enseñe qué ha hecho, o acabas revisando cincuenta cambios de golpe.
Sigue sin él. Es la pieza más prescindible de las cuatro y llevaba meses parada la última vez que se comprobó. La librería funciona igual instalando los componentes a mano.
Las fuentes, para que lo compruebes tú
Nada de esta guía se cita de memoria. Cada enlace se abrió y se comprobó el día que se escribió: qué es, qué licencia tiene y si sigue mantenido. Si algo de aquí ya no cuadra, gana la fuente.
Esto que acabas de leer es formación y herramientas, y en tu empresa tendrá otra forma. Si quieres, lo miramos sobre tu proceso: media hora basta para saber si hay algo que automatizar o si se arregla ordenando lo que ya tienes.
Ver las sesionesRevisada el 2026-08-31. Publicada el 2026-08-31.
De esto hablo en mi Instagram, donde lo cuento en un minuto.