Volver al trabajo

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.

File Convention
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
Inputs 7

Button, Input, Textarea, Select, Checkbox, Radio, Switch

Display 4

Badge, Avatar, Card, Tooltip

Feedback 5

Alert, Toast, Progress, Spinner, EmptyState

Overlay 4

Dialog, DropdownMenu, Command, Tooltip

Navigation 3

Accordion, Tabs, Breadcrumb

Data Display 1

Table

Utility 6

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

index.css
: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 */
}
Vista previa del tema
Botón
Primary Secondary Outline
Input
jane@company.com
Tarjeta
Resumen del Proyecto Actualizado hace 2 horas
Tokens
BG
FG
Border
Action

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.

APEX Design System - Storybook Interface
47 Stories 29 MDX Pages 4 Breakpoints Live on Vercel

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)
01

Resolución de Dependencias

Calcula dependencias transitivas (BFS)

button → utils dialog → button, utils
02

Descarga desde Registry

Obtiene archivos .tsx del registry JSON

✓ Downloaded 4 component files
03

Transformación de Imports

Reescribe imports relativos a alias (@/)

../../lib/utils @/lib/utils
04

Instalación Completa

Componentes listos para usar

✅ 4 components installed ✅ Ready to import
05

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.

registry/
  registry.json # Master index (29 component names)
  components/
    button.json # Component metadata
    dialog.json
    utils.json # Shared utility (cn function)
    use-theme.json # Theme hook
    ... (31 files)
button.json
{
  "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.

button dialog card utils

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

70 %

Más rápido en setup

De 3 horas a 20 minutos en configuración inicial de componentes

100 %

Accesibilidad garantizada

31 tests automatizados aseguran cumplimiento WCAG 2.1 AA en todos los componentes

85 %

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

React 19TypeScriptTailwind CSS 3Radix UICVAStorybook 10Vitestvitest-axeViteVercel

CLI Tool

Node.jsTypeScriptCommander.jsZodPromptsChalkOraExecafs-extratsup
Volver a todos los proyectos