Product Design

Cómo gobernar un design system en 10+ proyectos consumidores

Un playbook práctico para gobernar un design system en muchos proyectos consumidores: modelo de contribución, versionado, codemods y adopción.

27 de abril de 20268 min de lectura
Cómo gobernar un design system en 10+ proyectos consumidores

Publicas un design system. Un proyecto lo consume. Fácil. Cinco proyectos lo consumen. Manejable. Diez o más proyectos lo consumen, cada uno en una versión distinta, con sus propios plazos y sus propios ingenieros que abren tickets a las dos de la madrugada, y el sistema deja de escalar. Los tokens se desvían. Los breaking changes bloquean los trenes de release. Nadie sabe quién es dueño del componente Button este trimestre.

Esta guía recorre las siete jugadas que mantienen útil un design system cuando diez o más proyectos consumidores dependen de él. El resultado es un modelo de gobernanza que te permite enviar rápido sin romper a los consumidores, con un equipo core que sigue siendo pequeño, y métricas de adopción que puedes defender en una revisión trimestral.

La forma del problema

Un design system que sirve a un proyecto es una librería de componentes. Un design system que sirve a diez proyectos es una plataforma interna. El trabajo ya no consiste en añadir componentes. Consiste en coordinar el cambio en una flota que no posees, donde cada consumidor tiene su propio roadmap, su propia versión de React y su propia tolerancia a las migraciones.

Vuelven tres modos de fallo. Primero, los consumidores hacen fork del sistema para desbloquearse y no vuelven nunca. Segundo, el equipo core bloquea cada cambio en code review y se convierte en un cuello de botella. Tercero, los breaking changes se publican sin un camino de migración, y los consumidores se quedan en una versión de hace dos años porque actualizar cuesta un sprint.

Los siete pasos siguientes abordan cada modo de fallo de frente.

Paso 1: elige un modelo de contribución y ponlo por escrito

Existen tres modelos. Cada uno encaja en una forma de equipo distinta.

Centralizado. Un único equipo dedicado posee todo. Coherencia fuerte, escalado lento. Como escribió Nathan Curtis en el artículo canónico de EightShapes, los overlords no escalan. Úsalo solo cuando el sistema es joven y los consumidores son menos de cinco.

Federado. Muchos equipos contribuyen. Sin un dueño único. Rápido a corto plazo, caro a largo: los componentes divergen, las decisiones se arrastran, la coherencia cae. La federación pura es rara y no la recomendamos.

Híbrido (cíclico). Un pequeño equipo core posee la API, los tokens y la pipeline de release. Contribuidores embebidos en los equipos de producto envían componentes y proponen cambios. Salesforce lo describe como un modelo cíclico: gobernanza centralizada más contribución federada, cada uno informando al otro.

Para 10 o más consumidores, el híbrido es casi siempre la respuesta correcta. Documenta el modelo en un CONTRIBUTING.md en la raíz del repositorio: quién puede hacer merge a main, quién puede proponer componentes, quién decide sobre los tokens, cuál es el SLA en la revisión de PRs. Sin ese documento, cada escalado se convierte en una reunión.

Paso 2: congela la API pública

La mayor fuente de roturas accidentales en un design system es exportar cosas que no querías exportar. Un consumidor importa una utilidad privada, tú la refactorizas seis meses después, su build se rompe a las dos de la madrugada.

Define una superficie de API pública de forma explícita. Un único archivo barrel (un index.ts en la raíz del paquete) exporta los componentes, tokens, hooks y tipos que los consumidores pueden usar. Todo lo demás es interno. Configura el bundler para que los módulos internos no sean accesibles mediante deep imports, o añade una regla de ESLint (no-restricted-imports) que prohíba los deep imports en los proyectos consumidores.

Esta única jugada convierte el 80% de las roturas accidentales en roturas intencionales planificables.

Paso 3: versiona con SemVer, publica un changelog en cada release

Usa Semantic Versioning a nivel de paquete. MAJOR indica cambios de API no compatibles. MINOR añade funcionalidad compatible hacia atrás. PATCH corrige bugs sin cambiar el comportamiento. Atlassian y otros grandes publishers también versionan cada componente de forma independiente, dando a los consumidores notas de release más granulares; para un equipo core pequeño, el versionado a nivel de paquete es suficiente y más fácil de comunicar.

Cada release publica una entrada de changelog que indica: qué cambió, a quién afecta y (para releases MAJOR) el camino de migración. Herramientas como Changesets o release-please lo automatizan a partir de las descripciones de las PRs, así los contribuidores escriben el changelog mientras hacen merge, no a posteriori.

La disciplina que importa: un bump MAJOR nunca es silencioso. Los consumidores se enteran por el changelog o por un mensaje de Slack, jamás por una build de CI rota.

Paso 4: publica codemods con cada breaking change

Un breaking change sin camino de migración es un impuesto sobre cada consumidor. Con diez consumidores, ese impuesto se acumula: diez ingenieros, diez contextos que cargar, diez ocasiones para un error de tipeo.

La solución es jscodeshift o una herramienta de transformación AST similar. Cuando renombras una prop, eliminas un componente o cambias una ruta de import, escribes un codemod y lo publicas en la misma release que el breaking change. Tanto MUI como Chakra UI publican codemods con sus major versions, y los consumidores ejecutan un único comando para migrar.

Dos reglas prácticas:

  • Prueba el codemod primero contra el consumidor más grande. Los codemods que se rompen en casos límite son peor que no tener codemod, porque los consumidores dejan de confiar.
  • Empaqueta los codemods en una CLI dentro del paquete del design system, para que el camino de upgrade sea un único comando documentado y no una búsqueda en GitHub.

El equipo de Hypermod ha documentado en detalle el patrón design system dirigido por codemods; su argumento central es que la migración automatizada cambia la economía de los breaking changes de "no podemos permitirnos romper" a "podemos refactorizar libremente mientras el codemod siga".

Paso 5: rastrea la adopción con un manifest por consumidor

No puedes gobernar lo que no puedes medir. Cada proyecto consumidor debería publicar un ds.manifest.json en su raíz, commiteado en git, que registre:

  • La versión actual del design system de la que depende.
  • El número de componentes del design system realmente usados (contados a partir de los imports).
  • El número de overrides (CSS custom que rodea el sistema).
  • La fecha de la última auditoría manual.

Un job nocturno agrega estos manifest en toda la flota y produce un único dashboard. Los números que importan son la coverage (porcentaje de archivos UI que importan el design system), la deriva (número de overrides CSS por proyecto) y la distancia de versión (cuántas releases MAJOR de retraso lleva cada consumidor).

Brevo, Productboard y Mews han publicado todas su versión de este enfoque. El adoption tracker de Brevo y el coverage report de Productboard son buenas referencias públicas. La idea compartida: las métricas de adopción derivadas del código de producción ganan cada trimestre a las basadas en encuestas.

Paso 6: fija plazos de deprecation y hazlos cumplir

Un componente deprecado que vive para siempre no está deprecado, está soportado. Para deprecar limpiamente:

  1. Marca el componente como deprecado en el código fuente (una etiqueta JSDoc @deprecated, un warning en consola en desarrollo).
  2. Anuncia una fecha de eliminación en el changelog. Usamos 6 meses desde el anuncio para componentes de bajo tráfico, 12 meses para los de alto tráfico.
  3. Rastrea qué consumidores siguen importando el componente deprecado usando el manifest del Paso 5.
  4. Envía recordatorios dirigidos a 90 días, 30 días, 7 días de la eliminación.
  5. Elimina en la fecha anunciada, en una release MAJOR, con un codemod.

La parte más difícil es hacer cumplir el plazo. Los equipos piden prórrogas, y conceder prórrogas le enseña a todos que los plazos son negociables. No lo hagas.

Paso 7: mantén una cadencia de bump fija

Sin una cadencia, los consumidores actualizan al azar y la dispersión de versiones en la flota crece sin límite. Una cadencia quincenal o mensual funciona para la mayoría de los equipos. La cadencia tiene tres artefactos:

  • Una release programada en un día fijo (nosotros usamos el primer martes del mes).
  • Un chequeo pre-vuelo la semana anterior, que escanea los manifest de los consumidores en busca de riesgo: qué proyectos tienen más overrides, mayor distancia de versión o mayor uso de componentes deprecados.
  • Una retrospectiva tras cada release, revisando qué se rompió y por qué.

El objetivo es la previsibilidad. Los consumidores pueden planificar medio día por ciclo para el upgrade. Los ingenieros no reciben llamadas por migraciones sorpresa.

Qué estás sacrificando

Esta configuración no es gratis. El equipo core dedica tiempo real a changelogs, codemods, seguimiento de deprecations y la pipeline del manifest. Para un sistema que sirve a menos de cinco consumidores, el overhead es difícil de justificar y un proceso más ligero gana. Pasados los diez consumidores, el overhead se paga en dos ciclos de release, porque la alternativa es un apaga-fuegos reactivo que escala peor que un pequeño equipo de plataforma.

El otro sacrificio es la autonomía. Un modelo híbrido con una API pública congelada significa que los contribuidores no pueden enviar lo que quieran de la noche a la mañana. Proponen, el equipo core revisa, el cambio entra en la próxima release. Es más lento que dejar que cada equipo parchee el sistema in situ. También es la única manera de mantener a diez consumidores en la misma versión de Button.

Para una mirada más profunda al tipo de errores que este modelo de gobernanza previene, mira nuestro artículo sobre errores de design system que destrozan la coherencia a escala.

Foto de Ilya Semenov en Unsplash

Studio

Empieza un proyecto.

Un partner único para empresas, sector público, startups y SaaS. Producción más rápida, tecnología moderna, costes reducidos. Un equipo, una factura.