Módulo 1: What A Design System Is
Proyecto: el inventario del sistema de diseño de Mercado
Descripción
Las siete lecciones anteriores te enseñaron a leer un sistema de diseño: qué problema resuelve (el drift), sus cuatro capas, sus tres resultados (consistencia, mantenibilidad, accesibilidad) y la anatomía completa de Mercado. Este proyecto te pone a hacerlo. Vas a producir el inventario del sistema de diseño de Mercado —el plano, en tus propias manos— y, sobre todo, a detectar el drift de una versión ad-hoc del storefront, comprobándolo con un modelo ejecutado en Node.
El entregable tiene dos partes, y las dos importan. La parte A es el inventario declarado: la lista de tokens que el storefront necesita, y los componentes con sus variantes —lo que el sistema debería tener—. La parte B es la auditoría: tomar una versión ad-hoc del storefront (donde los valores se escribieron a mano) y demostrar, con un número, que tiene drift —que un rol que debería tener un valor tiene varios—. Juntas, las dos partes prueban que entiendes lo esencial del módulo: no solo qué es un sistema, sino cómo distinguir uno coherente de un montón de estilos sueltos, con evidencia y no con opinión.
Conexión con el módulo. Este proyecto es la síntesis de las siete lecciones. La parte A ejercita el inventario por capas (L3) y la anatomía de Mercado (L7), con tokens nombrados por rol (L1) y sin drift interno (L7). La parte B ejercita la medición del drift (L2, L4) como evidencia dura. Y todo apunta al por qué del módulo (L4-L6): un inventario limpio es la precondición de la consistencia, la mantenibilidad y la accesibilidad que los módulos siguientes construirán sobre estas piezas. Al terminar, quedas listo para el módulo 2, donde el primer token del inventario deja de ser un nombre y se vuelve un valor real en CSS.
Qué vas a construir
El entregable es un archivo de Node —inventory.js— que, al correrse, imprime:
- El inventario del sistema (parte A): los tokens de Mercado organizados por grupo (color, space, type) y los componentes con sus variantes. Esto es el plano de la L7, reproducido por ti.
- La auditoría de drift (parte B): tomando la lista de valores ad-hoc de un rol (el color primary escrito a mano en varias pantallas), cuenta cuántos valores distintos hay y emite un veredicto —
OKsi es 1,DRIFTsi hay más—.
No hay CSS ni JSX que escribir en este proyecto: es puro modelo en Node, como todos los "Qué esperar" del módulo. La razón es la del módulo entero —el navegador no corre aquí, así que mostramos lo que se escribiría y ejecutamos la lógica que lo valida—. El CSS y el JSX reales llegan a partir del módulo 2, cuando empieces a fabricar las piezas que aquí inventarias.
Una analogía: el inventario de la ferretería antes de abrir
Antes de abrir una ferretería, el dueño hace dos cosas. Primero, un inventario: lista qué tiene —cuántos martillos, qué medidas de tornillos, qué tipos de pintura— para saber con qué cuenta. Segundo, una revisión de calidad: abre las cajas y verifica que los tornillos "de 3 pulgadas" midan de verdad 3 pulgadas y no una mezcla de 2.9 y 3.1 que se colaron del proveedor descuidado.
El inventario sin la revisión es peligroso: puedes creer que tienes "tornillos de 3 pulgadas" cuando en realidad tienes cuatro medidas distintas etiquetadas igual —y un cliente que compra dos se lleva dos tamaños—. La revisión sin el inventario es incompleta: verificas cajas sueltas sin saber si tienes todo lo que la tienda necesita. Las dos juntas te dan una ferretería que sabe qué tiene y sabe que lo que tiene es coherente.
Tu proyecto es exactamente eso. La parte A es el inventario: qué piezas tiene el sistema de Mercado. La parte B es la revisión de calidad: verificar que un rol ("el azul de marca") no tenga cuatro valores colados etiquetados igual. Un sistema de diseño, como una buena ferretería, necesita las dos: saber qué tiene, y saber que cada cosa es una sola cosa.
Especificación del proyecto
Tu inventory.js debe cumplir esto:
Parte A — el inventario.
- Define un objeto
systemcon al menos:tokens(con gruposcolor,space,type) ycomponents(al menosButton,ProductCard,SearchBar, cada uno con sus ejes de variante). - Los tokens de color van nombrados por rol (
color.primary, noblue), y sin drift interno (un token por rol; L7). - Imprime el conteo de tokens y la lista por grupo, y los componentes con sus variantes.
Parte B — la auditoría de drift.
- Define
adHocPrimary: la lista del "azul de marca" tal como aparece escrito a mano en varias pantallas (con al menos un par de valores divergidos —el drift real—). - Cuenta los valores distintos (normalizando mayúsculas/minúsculas con
.toLowerCase(), como en L4). - Emite un veredicto:
OKsi hay exactamente 1 valor,DRIFT — unificar con el token color.primarysi hay más.
Restricciones (las convenciones del módulo):
- Todo identificador, token, clase y nombre de componente en inglés; solo comentarios y textos en español.
- Sin dependencias: puro JavaScript, corre con
node inventory.js. - Salida literal y reproducible.
Solución de referencia
Aquí está una solución completa que cumple la especificación. Estúdiala después de intentarlo por tu cuenta; el valor del proyecto está en construirlo tú, no en leer la respuesta:
// L8 proyecto — inventario del sistema de Mercado + deteccion de drift.
// PARTE A: el inventario declarado (lo que el sistema DEBERIA tener).
const system = {
tokens: {
color: ['color.primary', 'color.surface', 'color.text'],
space: ['space-2', 'space-4', 'space-6'],
type: ['text-sm', 'text-base', 'text-lg'],
},
components: {
Button: { variant: ['primary', 'secondary', 'ghost'], size: ['sm', 'md', 'lg'] },
ProductCard: { variant: ['default', 'compact'] },
SearchBar: { size: ['md', 'lg'] },
},
};
function countTokens(t) { return Object.values(t).reduce((n, a) => n + a.length, 0); }
console.log('=== INVENTARIO DEL SISTEMA DE MERCADO ===\n');
console.log('Tokens: ' + countTokens(system.tokens));
for (const [group, list] of Object.entries(system.tokens)) {
console.log(' ' + group.padEnd(7) + list.join(', '));
}
console.log('\nComponentes: ' + Object.keys(system.components).length);
for (const [name, axes] of Object.entries(system.components)) {
const variants = Object.entries(axes).map(([k, v]) => k + '=[' + v.join('|') + ']').join(', ');
console.log(' ' + name.padEnd(12) + variants);
}
// PARTE B: deteccion de drift en la version ad-hoc del "primary".
const adHocPrimary = ['#3b82f6', '#2563eb', '#3b82f6', '#3c83f6', '#3b82f6'];
const distinct = [...new Set(adHocPrimary.map((v) => v.toLowerCase()))];
console.log('\n=== DRIFT DETECTADO (color primary ad-hoc, 5 pantallas) ===');
console.log(' valores encontrados: ' + adHocPrimary.join(', '));
console.log(' valores distintos: ' + distinct.length + ' (deberia ser 1)');
console.log(' veredicto: ' + (distinct.length === 1 ? 'OK' : 'DRIFT — unificar con el token color.primary'));
Qué esperar. Al correr node inventory.js, la salida es exactamente esta:
=== INVENTARIO DEL SISTEMA DE MERCADO ===
Tokens: 9
color color.primary, color.surface, color.text
space space-2, space-4, space-6
type text-sm, text-base, text-lg
Componentes: 3
Button variant=[primary|secondary|ghost], size=[sm|md|lg]
ProductCard variant=[default|compact]
SearchBar size=[md|lg]
=== DRIFT DETECTADO (color primary ad-hoc, 5 pantallas) ===
valores encontrados: #3b82f6, #2563eb, #3b82f6, #3c83f6, #3b82f6
valores distintos: 3 (deberia ser 1)
veredicto: DRIFT — unificar con el token color.primary
Lee la salida como el entregable que es, en sus dos mitades.
La parte A es tu plano. Nueve tokens en tres grupos, tres componentes con sus variantes. Fíjate en lo que no tiene: no hay dos tokens para el mismo color (sin drift interno, L7), no hay ningún token nombrado por su valor (color.primary, no blue, L1). Es un inventario limpio: cada token es un rol, cada componente una pieza, todo en su capa. Este es el conjunto mínimo con el que se puede levantar el storefront de Mercado —y sobre el que los módulos siguientes construirán—.
La parte B es tu revisión de calidad, y aquí está la prueba de fuego del módulo. Tomaste "el azul de marca" tal como se escribió a mano en cinco pantallas (#3b82f6, #2563eb, #3b82f6, #3c83f6, #3b82f6), y el modelo contó 3 valores distintos donde debería haber 1. El #3b82f6 se repite (tres veces), pero #2563eb y #3c83f6 son intrusos —dos azules que se colaron, cada uno de una pantalla distinta, ninguno decidido por nadie—. El veredicto es contundente y contable: DRIFT. No "se ve un poco disparejo"; 3 en vez de 1, con el nombre del culpable y la cura (unificar con el token color.primary). Eso es distinguir un sistema de un montón de estilos sueltos con evidencia, que es exactamente lo que este módulo te enseñó a hacer.
Junta las dos mitades y tienes la tesis del módulo entero en un solo archivo: la parte A es el sistema (una verdad por rol), la parte B es lo que pasa sin él (varias verdades para un rol), y el token color.primary de la parte A es, precisamente, lo que curaría el drift de la parte B. El plano y la enfermedad que el plano previene, lado a lado.
Extensiones (opcionales, para ir más lejos)
Si quieres exprimir el proyecto, prueba estas ampliaciones —cada una refuerza una lección del módulo—:
- Combinaciones por componente (L7). Agrega al inventario, junto a cada componente, cuántas combinaciones produce (el producto de sus ejes:
Button= 3 × 3 = 9). Verás la economía del sistema hecha número. - Drift multi-rol (L4). Extiende la parte B para auditar varios roles a la vez (color, spacing, radius) y calcular un drift score total (
suma de (distintos − 1)). Un solo número para el desorden del storefront entero. - Costo del cambio (L5). Agrega una tercera parte que, dado un cambio de valor del token, cuente cuántas ediciones cuesta en ad-hoc (una por uso) contra en el sistema (siempre 1).
- Auditoría de accesibilidad (L6). Modela una lista de botones con
focusVisibleycontrastOk, y cuenta cuántos son accesibles ad-hoc contra los que serían con el componenteButtondel sistema.
Ninguna es necesaria para cumplir el proyecto; todas son buen entrenamiento para el resto de la guía.
Errores comunes
Entregar solo el inventario y saltarse la auditoría. Qué pasa: se hace una linda lista de tokens y componentes (parte A) y se olvida la detección de drift (parte B). Por qué pasa: el inventario se siente como "el" entregable, y es la parte más agradable de hacer. Cómo detectarlo: tu inventory.js lista piezas pero no demuestra nada sobre coherencia. Cómo corregirlo: el módulo no era solo "sabe listar las capas"; era "sabe distinguir un sistema de un caos, con evidencia". La parte B —el número que prueba el drift— es la que cierra ese aprendizaje. Como en la ferretería: el inventario sin la revisión de calidad puede estar lleno de tornillos de medidas mezcladas etiquetados igual. Entrega las dos partes.
Meter drift en el propio inventario (parte A). Qué pasa: al armar la lista de tokens, se cuelan dos nombres para un mismo rol (color.primary y color.brand) o un token nombrado por valor (blue600). Por qué pasa: el inventario se escribe rápido y no se revisa contra sí mismo. Cómo detectarlo: tienes más de un token para el azul de marca —el drift de la L4, ahora en la definición del sistema (fue justo el ejercicio 3 de la L7)—. Cómo corregirlo: un token por rol, nombrado por rol. Antes de dar por bueno el inventario, pásale la misma prueba de la parte B a tu propia lista de colores: ¿hay dos que sean el mismo rol? Si sí, únelos. La cura no puede tener la enfermedad.
Contar los strings sin normalizar y creer que no hay drift. Qué pasa: en la parte B, se cuentan los valores tal cual y, si por casualidad están escritos idénticos, se concluye "no hay drift" —perdiendo casos donde el mismo color está en mayúsculas y minúsculas (#3B82F6 vs #3b82f6) o el mismo espacio en 16px y 1rem—. Por qué pasa: el Set compara strings exactos, y dos representaciones del mismo valor cuentan como distintas (o, al revés, #3B82F6 y #3b82f6 son el mismo color contado como dos). Cómo detectarlo: tu conteo cambia si cambias mayúsculas por minúsculas, o mezcla px con rem. Cómo corregirlo: normaliza antes de contar —.toLowerCase() para los colores (como en la solución), y rem→px para los espacios (como en L2/L4)—. La normalización es lo que hace que el modelo mida el valor real y no su forma de escribirlo; sin ella, el drift score miente en ambas direcciones.
Rúbrica de autoevaluación
Marca cada punto; si todos están, dominaste el módulo:
- Inventario por capas. Tu
systemtiene tokens (agrupados) y componentes con variantes, con nombres en inglés. - Tokens por rol, sin drift interno. Los colores se llaman por su rol (
color.primary), y no hay dos tokens para un mismo rol. - Auditoría ejecutada. La parte B cuenta valores distintos de un rol ad-hoc y emite un veredicto (
OK/DRIFT). - Normalización. El conteo normaliza (mayúsculas/minúsculas) para medir el valor y no su forma.
- Salida literal. Corriste
node inventory.jsde verdad y la salida coincide con lo que reportas —no inventaste el output—. - Sin residuo. El archivo corre limpio, sin dependencias, sin errores.
Resumen y cierre del módulo
Con este proyecto cerraste el módulo 1 haciendo, no solo leyendo. Produjiste el inventario del sistema de diseño de Mercado —el plano en tus manos: tokens por rol, componentes con variantes, todo en su capa— y, más importante, detectaste el drift de una versión ad-hoc con evidencia dura: 3 valores para un rol que debía tener 1, veredicto DRIFT, culpable y cura nombrados. Con la ferretería antes de abrir viste que un sistema necesita las dos cosas —saber qué tiene (inventario) y saber que cada cosa es una sola cosa (auditoría)—, y las entregaste ambas, ejecutadas en Node.
Da un paso atrás y mira lo que aprendiste en las ocho lecciones. Sabes qué es el drift y que es contable (L1-L2); sabes que un sistema se organiza en cuatro capas —tokens, utilidades, componentes, patrones— cada una sobre la de abajo (L3); y sabes que la consistencia (L4), la mantenibilidad (L5) y la accesibilidad (L6) no son metas que se persiguen aparte, sino resultados que caen solos cuando cada decisión vive en un lugar y todo la referencia. Tienes el mapa mental completo: qué problema resuelve un sistema y de qué piezas se compone.
Lo que no hiciste todavía —a propósito— es fabricar una sola de esas piezas. No definiste el valor de color.primary, no escribiste una clase de Tailwind, no construiste el Button. Eso empieza ahora. El módulo 2 — Design Tokens toma la primera capa de tu inventario y la vuelve real: vas a definir los tokens en CSS (primitivos vs semánticos vs de componente), a darles valor en tema claro y oscuro, y a ejecutar un resolveToken que resuelve un token semántico hasta su valor final. El plano que trazaste aquí se empieza a construir, ladrillo por ladrillo, empezando por los cimientos.
Recursos
- Design Tokens Community Group (W3C) — tr.designtokens.org/format. El estándar para describir un inventario de tokens como el que hiciste; la referencia formal que abre el módulo 2. En inglés.
- Brad Frost, "Doing Atomic Design" — atomicdesign.bradfrost.com/chapter-4. Cómo llevar un sistema de piezas del inventario a la práctica; complementa este proyecto con el "cómo" del proceso. En inglés.
- shadcn/ui, "Components" — ui.shadcn.com/docs/components. Un inventario de componentes con variantes construido de verdad, para comparar con el tuyo. En inglés.
- Material Design 3, "Design tokens" — m3.material.io/foundations/design-tokens/overview. Cómo un sistema real organiza y nombra su inventario de tokens; el siguiente nivel de lo que empezaste aquí. En inglés.