El error que mata tu design system: tokens sin validación
Los design tokens sin auditoría automática generan inconsistencias visuales en producción. Te mostramos cómo detectarlas antes del PR.
Equipo NUCBA
El error que mata tu design system: tokens sin validación
Estás a dos commits de mergear. El componente se ve bien en Figma, el código compila, los tests pasan. Tres semanas después, tu app tiene cinco tonos diferentes de azul primario, y nadie sabe cuál es el correcto. El culpable no es el equipo de desarrollo: es tu sistema de tokens sin validación automática.
Los design tokens son variables que almacenan decisiones visuales (colores, tipografías, espaciados). Pero sin auditoría, se convierten en una fuente de verdad que miente. Un desarrollador usa color.primary mientras otro hardcodea #3B82F6 porque "se ve igual". El resultado: inconsistencias que nadie detecta hasta que un usuario las reporta.
Por qué los tokens sin auditoría rompen la consistencia visual
Un design system sin validación automática confía en que todos harán lo correcto. Pero la realidad es diferente: deadlines apretados, nuevos devs que no conocen el sistema, y esa variante de componente que "necesitábamos ayer".
El problema no es la falta de documentación. Podés tener una guía perfecta de 50 páginas y aún así encontrarás hardcoded values en producción. El problema es que no hay nada que impida mergear código que ignora tus tokens.
Inconsistencias comunes que escapan al code review
- Valores hardcodeados:
padding: 12pxen lugar despacing.3(que vale 12px). Se ven idénticos, pero cuando cambiás tu escala de espaciado, uno se actualiza y el otro no. - Tokens deprecados: Ese
color.blue500que reemplazaste porcolor.primaryhace dos meses, pero todavía vive en 47 archivos. - Valores "casi iguales":
#3B82F6vs#3B83F6. Nadie nota la diferencia hasta que los ponés lado a lado en producción. - Tokens de contexto equivocado: Usar
text.bodypara un tamaño de botón porque "casualmente mide 16px".
El code review no escala para detectar esto. Necesitás automatización.
Cómo detectar tokens inválidos antes del PR
La estrategia es simple: si no está en tu sistema de tokens, no pasa CI. Esto no es ser estricto, es proteger la consistencia visual de tu producto.
1. Linters para CSS/SCSS
Configurá reglas que fuercen el uso de tokens en propiedades visuales:
// stylelint.config.js module.exports = { rules: { 'scale-unlimited/declaration-strict-value': [ ['/color$/', 'fill', 'stroke', 'background', 'border'], { ignoreValues: ['transparent', 'inherit', 'currentColor'], disableFix: true } ], 'declaration-property-value-allowed-list': { 'padding': ['/^var\\(--spacing-/'], 'margin': ['/^var\\(--spacing-/'], 'gap': ['/^var\\(--spacing-/'] } } }
Este setup rechaza cualquier color hardcodeado y fuerza que spacing use variables CSS.
2. Validación en JavaScript/TypeScript
Si usás CSS-in-JS, TypeScript puede validar tokens en build time:
// tokens.ts export const spacing = { 1: '4px', 2: '8px', 3: '12px', 4: '16px', // ... } as const; export type SpacingToken = keyof typeof spacing; // componente.tsx interface BoxProps { padding: SpacingToken; // Solo acepta claves válidas } const Box = ({ padding }: BoxProps) => ( <div style={{ padding: spacing[padding] }} /> ); // ✅ Compila <Box padding={3} /> // ❌ Error de TypeScript <Box padding={13} />
3. Tests visuales que detectan desviaciones
Los visual regression tests no solo detectan bugs, también marcan cuando alguien usó un valor fuera del sistema:
// design-token.test.js import { getComputedStyle } from './test-utils'; import { validColors } from './tokens'; test('Todos los colores en producción están en el sistema', () => { const elements = document.querySelectorAll('*'); const usedColors = new Set(); elements.forEach(el => { const styles = getComputedStyle(el); usedColors.add(styles.color); usedColors.add(styles.backgroundColor); }); usedColors.forEach(color => { expect(validColors).toContain(color); }); });
Este test falla si cualquier elemento usa un color que no está declarado en tus tokens.
4. Pre-commit hooks que bloquean merges
Git hooks evitan que código inválido llegue al PR:
// package.json { "husky": { "hooks": { "pre-commit": "lint-staged" } }, "lint-staged": { "*.{css,scss}": [ "stylelint --fix", "design-token-validator" ], "*.{ts,tsx}": [ "eslint --fix", "tsc --noEmit" ] } }
Si el código no pasa las validaciones, el commit no se crea. Simple.
Checklist: implementá validación de tokens esta semana
Esta es la secuencia para agregar validación a un design system existente sin frenar el equipo:
- Auditá el código actual: Corré un script que detecte todos los valores hardcodeados. No los arregles todavía, solo medí el problema.
- Documentá los tokens válidos: Creá una lista canónica de tokens en un archivo importable (JSON, TypeScript, lo que uses).
- Configurá el linter: Instalá
stylelintoeslint-plugin-design-tokenscon reglas permisivas al principio. - Modo warning primero: Dejá que las validaciones fallen sin bloquear CI durante una semana. Esto educa al equipo sin frenar entregas.
- Migrá código crítico: Arreglá primero los componentes más usados (buttons, inputs, cards).
- Activá el modo error: Una vez que la mayoría del código está limpio, hacé que las validaciones bloqueen merges.
- Automatizá la sincronización: Si tu fuente de verdad es Figma, usá plugins como Tokens Studio para exportar automáticamente a código.
El costo real de no validar tokens
Un equipo de producto que trabajamos tenía 23 versiones diferentes de su color primario en producción. No era negligencia: era el resultado natural de seis meses sin validación automática.
El rediseño para corregirlo tomó tres sprints. Tuvieron que:
- Identificar todos los usos del color (incluyendo imágenes y assets)
- Decidir cuál era el "verdadero" azul primario
- Actualizar componentes uno por uno
- Lidiar con bugs visuales que aparecieron al normalizar
Todo esto se hubiera evitado con un linter que rechazara #3B82F6 en el primer PR.
El tiempo que "ahorrás" al no configurar validaciones lo pagás multiplicado por diez en deuda técnica.
Preguntas frecuentes
¿Qué pasa con los valores únicos que realmente necesito?
Creá un sistema de escape explícito. En lugar de hardcodear, usá un comentario especial que el linter reconozca:
.special-case { /* design-token-disable-next-line */ color: #FF6B9D; /* Marca cliente, aprobado por diseño */ }
Esto deja registro de por qué ese valor existe y facilita auditorías futuras.
¿Los linters no hacen el proceso más lento?
Al principio, sí. La primera semana vas a tener fricción. Pero después de que el equipo internaliza los tokens, el proceso se acelera: menos decisiones visuales, menos idas y vueltas en los PRs, menos bugs de inconsistencia.
¿Cómo convenzo al equipo de implementar esto?
Mostrá el costo real. Hacé una auditoría rápida: cuántos colores únicos hay en tu app vs cuántos deberían existir según el design system. El número suele ser escandaloso y vende solo la necesidad de validación automática.