APEX Design System
Un sistema de diseño de grado productivo con herramientas CLI para aplicaciones SaaS
Video placeholder: Website + CLI demo
APEX es un sistema de diseño completo para aplicaciones SaaS/B2B, construido desde cero con React 19, TypeScript y Tailwind CSS. Incluye 30 componentes accesibles y conscientes del tema, documentación interactiva vía Storybook, y una herramienta CLI estilo Shadcn que permite a los desarrolladores instalar componentes directamente en sus proyectos con un solo comando.
Contexto
Desafío
La mayoría de los sistemas de diseño en la industria caen en uno de dos extremos — y ninguno es ideal para equipos que necesitan tanto facilidad de uso como control total.
Paquetes npm
Fáciles de instalar pero difíciles de personalizar. Estás atado a su API y decisiones de estilo. Material UI, Chakra UI siguen este modelo.
Colecciones de copiar-pegar
Totalmente personalizables pero sin herramientas de instalación, sin gestión de dependencias, sin versionado. El antiguo Tailwind UI era así.
APEX: Impulsado por CLI
Un CLI copia el código fuente del componente directamente en tu proyecto. Propiedad total con colocación automatizada de archivos, resolución de dependencias y configuración de imports.
Shadcn/ui fue pionero en este tercer enfoque. El objetivo con APEX era construir un sistema de diseño que cubra todo el espectro — desde tokens de diseño hasta instalación automatizada — al nivel de calidad esperado de un ingeniero frontend senior.
Fase 1
Enfoque
Decisiones de Arquitectura
Cada elección se hizo con una razón clara — favoreciendo la composabilidad, seguridad de tipos y accesibilidad por defecto.
| Decisión | Elección | Razón |
|---|---|---|
| Primitivos de componentes | Radix UI | Headless, accesible por defecto, composable. 13 primitivos usados. |
| Gestión de variantes | CVA | API de variantes type-safe, funciona nativamente con Tailwind. |
| Estilos | Tailwind CSS 3 | Utility-first con tokens de diseño semánticos para tematización. |
| Documentación | Storybook 10 | Playground interactivo, auditoría de accesibilidad, testing responsivo. |
| Testing | Vitest + axe | Rápido, compatible con React 19, axe-core para accesibilidad. |
| Despliegue | Vercel | Sin configuración, auto-deploys desde GitHub en cada push. |
Librería de Componentes — 30 Componentes
Cada componente sigue una convención de archivos estricta con implementación, stories, documentación, tests e índice de exportación público. Construido para consistencia y descubribilidad.
src/components/{Name}/
├── {Name}.tsx # Component implementation
├── {Name}.stories.tsx # Storybook stories
├── {Name}.mdx # Documentation
├── {Name}.test.tsx # Tests (selected components)
└── index.ts # Public exports Button, Input, Textarea, Select, Checkbox, Radio, Switch
Badge, Avatar, Card, Tooltip
Alert, Toast, Progress, Spinner, EmptyState
Dialog, DropdownMenu, Command, Tooltip
Accordion, Tabs, Breadcrumb
Table
Label, HelperText, ErrorMessage, FieldGroup, Divider, ThemeToggler
Sistema de Tokens de Diseño
Todas las propiedades visuales están impulsadas por propiedades CSS personalizadas, permitiendo tematización en tiempo de ejecución. Los tokens se mapean a Tailwind vía tailwind.config.ts, así los componentes usan nombres de clase semánticos como bg-semantic-bg-primary en lugar de colores hardcodeados.
Background
--color-bg-primary
Foreground
--color-fg-primary
Secondary
--color-bg-secondary
Border
--color-border-default
Action
--color-action-primary
Success
--color-success
Error
--color-error
Warning
--color-warning
:root {
--color-bg-primary: #ffffff;
--color-fg-primary: #0f172a;
--color-border-default: #e2e8f0;
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
/* 20+ semantic tokens */
}
.dark {
--color-bg-primary: #0f172a;
--color-fg-primary: #f8fafc;
/* Full dark mode overrides */
} Accesibilidad — WCAG 2.1 AA
La accesibilidad no fue una reflexión tardía. Se aplicó en tres niveles:
Nivel de Componente
Los primitivos de Radix UI proporcionan navegación por teclado, gestión de foco y atributos ARIA por defecto. Se añadieron atributos adicionales donde fue necesario.
Nivel Visual
Los estados deshabilitados usan tokens de color explícitos (no trucos de opacidad) para mantener una relación de contraste de 4.5:1. Los indicadores de foco usan focus-visible para visibilidad solo con teclado.
Nivel de Testing
31 tests automatizados en 8 componentes usando vitest-axe, que ejecuta auditorías de accesibilidad axe-core contra componentes renderizados.
Resultado
31 tests de accesibilidad automatizados, cumplimiento WCAG 2.1 AA en los 30 componentes, más soporte global de prefers-reduced-motion que desactiva todas las animaciones.
Documentación Storybook
47 stories organizados en Guías, Tokens de Diseño, Componentes y Patrones. Cada story de componente incluye variantes, estados y demos responsivas.
En acción
El sistema funcionando
Aplicación ficticia construida con los componentes de APEX
Fase 2
Herramienta CLI
¿Por qué construir un CLI?
El sistema de diseño es el producto. El CLI es el mecanismo de distribución. Sin él, un desarrollador necesitaría clonar el repo, encontrar los archivos correctos, copiarlos manualmente, averiguar las dependencias npm, instalarlas y arreglar todas las rutas de import.
El CLI automatiza todo esto en un solo comando: npx apex-cli add button. Solo ~5% de los sistemas de diseño en la industria tienen herramientas CLI.
Detección del Proyecto
Identifica Vite, Next.js, CRA o framework
✓ Detected: Vite (TypeScript) Resolución de Dependencias
Calcula dependencias transitivas (BFS)
button → utils dialog → button, utils Descarga desde Registry
Obtiene archivos .tsx del registry JSON
✓ Downloaded 4 component files Transformación de Imports
Reescribe imports relativos a alias (@/)
../../lib/utils → @/lib/utils Instalación Completa
Componentes listos para usar
✅ 4 components installed ✅ Ready to import Demo del Terminal
Arquitectura del Registry
El registry es la capa de datos central — 31 archivos JSON que describen los metadatos, archivos, dependencias y exportaciones de cada componente.
{
"name": "button",
"type": "registry:ui",
"title": "Button",
"description": "An interactive element that triggers actions...",
"category": "inputs",
"files": [{
"path": "../../saas-design-system/src/components/Button/Button.tsx",
"target": "components/ui/button.tsx"
}],
"dependencies": [
"class-variance-authority@^0.7.1",
"lucide-react@^0.563.0"
],
"registryDependencies": ["utils"],
"exports": ["Button", "buttonVariants", "ButtonProps"]
} Resolución de Dependencias
La función resolveDependencyTree() usa búsqueda en amplitud para resolver todas las dependencias transitivas. Las dependencias compartidas se deduplican automáticamente.
Transformación de Imports
Los componentes en el sistema de diseño usan imports relativos. Cuando se copian al proyecto del usuario, el transformador reescribe estos para coincidir con la configuración de alias del usuario.
Design System (relative)
import { cn } from '../../lib/utils'
import { useTheme } from '../../hooks/useTheme'
import { Button } from '../Button' User Project (aliased)
import { cn } from '@/lib/utils'
import { useTheme } from '@/hooks/use-theme'
import { Button } from '@/components/ui/button' Resultados
Impacto
Más rápido en setup
De 3 horas a 20 minutos en configuración inicial de componentes
Accesibilidad garantizada
31 tests automatizados aseguran cumplimiento WCAG 2.1 AA en todos los componentes
Mejor colaboración design-dev
Storybook como fuente única de verdad elimina discrepancias entre diseño e implementación
Especificaciones
Detalles Técnicos
30 Componentes
Inputs, Display, Feedback y Overlay listos para producción
47 Stories
Documentación interactiva completa en Storybook
CLI Dedicado
Herramienta de instalación con detección automática de framework
4 Frameworks
Soporte para Vite, Next.js, CRA y Remix
31 Tests A11y
Auditorías automáticas con axe-core integrado
13 Primitives
Radix UI como base para accesibilidad nativa
De Principio a Fin
Experiencia de Desarrollador
De cero a componentes funcionando en menos de 2 minutos. El CLI maneja detección de proyecto, configuración, resolución de dependencias, copia de archivos y transformación de imports.
Paso 1
Create a new React project
npm create vite@latest my-app -- --template react-ts Scaffolds a new Vite + React + TypeScript project
Paso 2
Initialize APEX
npx apex-cli init Detects project, configures paths, installs base dependencies
Paso 3
Browse components
npx apex-cli list Shows 29 components organized by category
Paso 4
Install components
npx apex-cli add button card input dialog Resolves dependencies, copies files, transforms imports
Paso 5
Use immediately
import { Button } from '@/components/ui/button' Full ownership — modify variants, styles, or behavior directly
Reflexión
Aprendizajes
01
Las herramientas CLI son un multiplicador
El sistema de diseño tiene valor por sí solo, pero el CLI lo transforma de un repositorio de código a una herramienta de desarrollador. Cambia la percepción de 'una colección de componentes' a 'un sistema instalable.'
02
La accesibilidad es una característica
Usar Radix UI como base y aplicar auditorías axe-core en tests detectó problemas que las pruebas manuales pasaron por alto. Los tokens de color semánticos para estados deshabilitados fueron un detalle no obvio pero importante.
03
El diseño del registry importa
El registry de componentes basado en JSON es la fuente única de verdad que hace posible el CLI. Acertar con el esquema — especialmente registryDependencies y type — fue la decisión arquitectónica clave.
04
La transformación de imports es compleja
La reescritura de imports basada en regex maneja el 90% de los casos, pero los casos edge requieren un ordenamiento cuidadoso de patrones. El transformador procesa de más específico a menos específico para evitar coincidencias falsas.
Design System
CLI Tool