ThemeForge: un sistema de temas CSS listo para usar; un agente de IA lo instala en un solo paso.

Categoría
IA y LLM Local
Publicado
5 octubre 2026
Actualizado
6 octubre 2026
Por
Jacob Lloyd — escrito con ayuda de IA, después del proyecto
Tiempo de lectura
35 min de lectura

En palabras simples: ThemeForge es una carpeta gratuita que contiene CSS y un pequeño script que le brinda a cualquier aplicación web un selector de temas, diez temas de colores y un conjunto completo de botones, campos, tarjetas y cuadros de diálogo ya listos para usar. Está diseñado de tal manera que un agente de codificación de IA pueda incorporarlo en una aplicación con una sola línea: el agente sigue las instrucciones de un archivo breve dentro del repositorio, y la aplicación obtiene así un selector funcional, un valor predeterminado acorde al sistema y tokens de diseño a partir de los cuales trabajar.

La mayoría de las aplicaciones web terminan teniendo tres temas, escritos en tres lugares distintos: un bloque :root en el CSS principal, un segundo bloque bajo @media (prefers-color-scheme: dark), y un tercero que algún desarrollador añadió para que el selector de temas funcionara. El resultado es siempre el mismo: un control que se ve de una manera en la página de inicio, de otra en la página de configuración, y luego surge una pregunta en el sistema de seguimiento de errores preguntando por qué el tema oscuro vuelve azul el pie de página. Escribí ThemeForge para impedir que este tipo de problemas ocurran. Se trata de una única carpeta, ui-theme/, que contiene el motor de ejecución, una capa base, las clases de componentes, los tokens de los diez temas, un selector de temas, adaptadores opcionales para Tailwind y Quasar, y un breve archivo AGENTS.md destinado a un agente de programación IA. Basta con colocar esa carpeta en el proyecto, añadir cuatro líneas al encabezado de la página, y la aplicación contará con un selector funcional y un tema predeterminado que sigue las preferencias del sistema. El agente encargado de la instalación lo hace mediante un único comando; el resto de este artículo está pensado para quienes deseen conocer su funcionamiento interno.

Este artículo sirve como guía: explica qué hay realmente en la carpeta, los diez temas y para qué sirven, la historia del contraste, así como los tokens de diseño y las clases de componentes que se detallan más adelante como referencia. La segunda mitad del texto está pensada para ser consultada fácilmente: cada token, cada componente, cada método público, para que cualquier agente de programación (o tú mismo en el futuro) pueda copiarlos tal cual.

Resumen rápido

  • Descarga: github.com/LaserLloyd/ThemeForge — licencia MIT, gratis; también hay un zip con el código en la sección de Descargas.
  • ¿Qué es?: una sola carpeta, ui-theme/, que se integra en cualquier aplicación web y le aporta diez temas de colores, un selector, unas 250 variables de diseño, una capa base de elementos, un estándar tipográfico y un conjunto completo de clases de componentes (botones, campos, interruptores, tarjetas, diálogos, avisos, tablas, estructura general). Solo CSS plano y un pequeño script. No requiere compilación, ni Node, ni dependencias.
  • Instalación en una sola línea (tal cual aparece en el README): python3 -c "import urllib.request as u,sys;sys.argv=['update.py','--dest','static/ui-theme'];exec(u.urlopen('https://raw.githubusercontent.com/LaserLloyd/ThemeForge/main/ui-theme/update.py').read())"
  • Orden del encabezado (es importante): primero ui-theme.js (clásico, bloqueante; nunca defer ni module), luego ui-theme-base.css y ui-components.css, después el CSS propio de la app, y finalmente ui-theme.css para que los tokens del tema tengan prioridad.
  • Selector de temas: un único elemento: <select class="ui-select" data-ui-theme-picker aria-label="Theme"></select>. Se rellena solo y permanece sincronizado entre pestañas.
  • Los diez temas: seis principales (Púrpura, Oro Nocturno, Glaciar, Bosque, Papel, Luz Diurna) más cuatro opcionales (Amarillo Eléctrico, LaserLloyd, LaserLloyd Claro, Rojo Noche). Todos superan la auditoría de contraste sin errores.
  • Contraste: texto principal 7:1, secundario 6:1; cualquier nivel de texto en cualquier superficie alcanza 4.5:1; los bordes y estados de activación 3:1; el estado “activado” o “seleccionado” se identifica por forma y relleno, no solo por color.
  • Diseñado para agentes IA: AGENTS.md es el script de instalación en formato textual; basta apuntar a él a cualquier agente para que configure el selector en un solo paso. El propio repositorio ejecuta tres tareas en GitHub Actions: clonado, auditoría de contraste, node --check en cada archivo JS y pruebas del motor mediante Chrome sin interfaz gráfica.

¿Dónde obtenerlo?

Un único repositorio bajo licencia MIT: github.com/LaserLloyd/ThemeForge, con AGENTS.md como guía de instalación y el informe de contraste como prueba de calidad. ¿Prefieres un zip? En la sección de Descargas al final de esta página encontrarás el código completo; la página Descargas del sitio también lo ofrece. Si tu máquina no cuenta con Python, el README indica usar git clone –depth 1, npx degit o la URL de jsDelivr <script> fijada a @v1.0.0 para prototipos rápidos.

¿Qué obtienes al final?

A un paso de lograr el aspecto preferido por el usuario: un encabezado con un selector que ya conoce todos los temas, un tema oscuro y uno claro predeterminados que siguen las preferencias del sistema, y una sola línea de CSS en el código que reemplaza #1d1d39 por background: var(–surface-2). Elige un tema, recarga la página y no habrá parpadeo alguno; el script de ejecución corre sincrónicamente en <head>, lee sus propias configuraciones data-* desde la etiqueta, y establece el tema antes de que se dibuje cualquier elemento. Abre el selector en dos pestañas, cambia el tema en una y la otra se actualiza automáticamente (gracias a un listener de storage). Si imprimes con un tema oscuro u OLED, el motor alterna temporalmente a uno claro durante la impresión (o oculta la navegación según el valor de data-print-theme) para que el papel sea legible; si usas un tema claro, la página se imprime tal cual.

Notas

Bandeja de entrada

3 notas, 1 sin leer

Revisión trimestral Fijado

Borrador de la retrospectiva del Q3 — necesito dos ejemplos más antes del viernes.

Lista de equipaje

Pasaporte, cargador, la linterna pequeña.

Una estructura de aplicación creada con ui-app, ui-card, ui-btn, ui-switch y los tokens --surface-* / --text-* / --accent. El selector es un simple <select data-ui-theme-picker>; el motor lo rellena y sincroniza.

La figura anterior es una demostración integrada en la página, no una captura de pantalla externa. El ejemplo completo —todos los componentes en cada tema— se encuentra en specimen/index.html del repositorio (puedes abrirlo ejecutando python3 -m http.server y accediendo a /specimen/).

Cómo se integra todo

El motor de ejecución es un pequeño script, ui-theme.js (aproximadamente 23 KB y 575 líneas) que realiza tres tareas en secuencia. Primero lee sus propios atributos data-* de la etiqueta <script> donde reside (de modo que la configuración viaje junto con el archivo), luego consulta localStorage y las preferencias del sistema para modo claro u oscuro, y finalmente escribe el tema elegido en <html data-palette> y el fondo activo en <html data-theme> (uno de amoled, dark, light) antes de que se dibuje cualquier elemento. A continuación recorre el documento en busca de elementos <select data-ui-theme-picker> y los rellena con la lista de temas disponibles (además de escuchar cambios posteriores generados por cualquier framework). Finalmente expone window.UITheme y, cuando se carga ui-components.js, también window.UIComponents; además instala un listener de storage para mantener sincronizadas las pestañas. El CSS es sencillo: ui-theme-base.css define el texto, los enlaces, el anillo de foco, las barras de desplazamiento y valores por defecto para movimientos reducidos; ui-components.css dibuja botones, campos, interruptores, tarjetas, diálogos, avisos y tablas; ui-theme.css es el único archivo que varía entre temas: define todos los tokens (color, tipografía, espaciado, radios, sombras, animaciones) para los diez temas bajo un selector [data-palette=”…”] (el tema Púrpura usa :root, es decir, sin atributo data-palette). El motor elige el tema; el CSS lo representa visualmente.

El seguimiento del tema del sistema operativo es lo que sorprende a muchos: data-default=”auto” lee prefers-color-scheme en cada carga de página; el motor combina ese valor con la elección guardada por el visitante (o con data-default-dark y data-default-light) para decidir el tema. Cambie el tema del sistema y actualice la página; esta se adaptará automáticamente. Si el usuario selecciona un tema manualmente, ese prevalecerá hasta que lo borre (o ejecute UITheme.reset()). El motor también utiliza un evento de storage para mantener sincronizadas dos pestañas abiertas de la misma aplicación, sin necesidad de comunicación con el servidor.

Instalación

El archivo AGENTS.md del repositorio contiene la guía completa; la versión breve consiste en una sola línea de comando y cuatro etiquetas en el encabezado. Desde la raíz de la aplicación:

python3 -c "import urllib.request as u,sys;sys.argv=['update.py','--dest','static/ui-theme'];exec(u.urlopen('https://raw.githubusercontent.com/LaserLloyd/ThemeForge/main/ui-theme/update.py').read())"

Este comando descarga el instalador, que a su vez obtiene la última versión, verifica cada archivo mediante la lista SHA-256 en files.json y escribe los archivos en la carpeta correspondiente. En Windows use python o py en lugar de python3; la línea funciona igual en PowerShell, cmd y bash. Las cuatro líneas que deben ir en el <head> de cada página:

<script src="/static/ui-theme/ui-theme.js"
        data-themes="purple,midnight-gold,glacier,forest,paper,daylight"
        data-default="auto" data-default-dark="midnight-gold" data-default-light="daylight"
        data-storage-key="myapp.theme"></script>
<link rel="stylesheet" href="/static/ui-theme/ui-theme-base.css">
<link rel="stylesheet" href="/static/ui-theme/ui-components.css">
<!-- sus hojas de estilo -->
<link rel="stylesheet" href="/static/ui-theme/ui-theme.css">

Tres reglas, cada una con su razón. El script ui-theme.js es clásico y bloqueante: nunca lleva type=”module”, defer ni async, porque lee sus propios atributos desde su propia etiqueta (document.currentScript, que es null para scripts tipo módulo) y establece el tema antes del primer renderizado. Las capas base y de componentes se cargan antes que el CSS de la aplicación, de modo que las reglas propias de esta prevalezcan cuando la especificidad sea igual. ui-theme.css se carga después, evitando así que variables antiguas de la app sobrescriban los tokens del tema. El selector para elegir el tema consta de una sola línea: <select class=”ui-select” data-ui-theme-picker aria-label=”Theme”></select>. Desde el código, se pueden usar UITheme.set(‘glacier’), UITheme.current() y UITheme.onChange(fn). Según el preámbulo de AGENTS.md, la instalación completa dura unos cinco minutos.

El agente que realizó todo esto en un solo paso, en una aplicación real, actuó así: el humano le pidió a un agente de programación IA que añadiera modo oscuro y selector de temas. El agente leyó AGENTS.md, ejecutó la línea de comando en static/ui-theme/, pegó las cuatro etiquetas del encabezado en la plantilla base, sustituyó dos valores de color por var(–surface-2) y var(–text-secondary), y colocó el selector en el encabezado. Seis líneas de diferencia en el código, cero dependencias nuevas. La auditoría de contraste ya cubre todas las combinaciones posibles que generan los componentes; el motor sigue automáticamente el tema del sistema operativo; y el único riesgo que detecta la herramienta de lint es que alguien codifique un color fijo en el futuro.

Los temas

Los seis primeros son los básicos que toda aplicación ofrece por defecto; los cuatro restantes aparecen solo si la app los declara explícitamente. Todos pasan la auditoría de contraste (docs/contrast-report.md): texto principal con ratio 7:1, texto secundario con 6:1 en cualquier fondo, todos los demás niveles de texto con 4.5:1; bordes y estados on/off con 3:1; además, en cada tema el estado seleccionado o activo se reconoce por forma y color. Lista completa:

Tema Conjunto Fondo Descripción
Purple básico oscuro Acento violeta y texto lavanda suave sobre índigo profundo. Es el tema base: sus valores son los predeterminados de :root.
Midnight Gold básico OLED Dorado cálido sobre negro puro, ideal para pantallas OLED.
Glacier básico OLED Texto y detalles azul hielo sobre negro puro, con un acento verde azulado intenso.
Forest básico OLED Verde pálido y marrón corteza sobre negro puro.
Paper básico claro Pergamino cálido, texto marrón tinta, tipografía serif para prosa y acento rojo.
Daylight básico claro Blanco limpio con acento azul.
Electric Yellow opcional oscuro Amarillo ácido sobre grafito; radios ajustados y trazos nítidos.
LaserLloyd opcional oscuro Azul láser sobre grafito casi negro, tal como aparece en el sitio web del autor. Se combina con LaserLloyd Light.
LaserLloyd Light opcional claro Versión clara de LaserLloyd.
Night Red opcional OLED Tema nocturno de baja luz azul: texto rojo cálido sobre negro puro, estructura roja y cero azul en ningún color.

Tres de los cuatro temas opcionales son llamativos por diseño. Electric Yellow es el que yo uso cuando reviso CSS en la oscuridad; quiero que la página destaque más que mi editor. LaserLloyd replica el aspecto azul y grafito de este sitio, para mantener coherencia entre él y la app que estoy desarrollando. Night Red es un “perfil nocturno” aparte; la herramienta de contraste lo analiza mediante un conjunto ampliado de 171 filas (las 147 estándar más otras para condiciones de poca luz), y en él ningún token del tema contiene componente azul (docs/contrast-report.md describe la “auditoría de cero azul”; README.md incluye la sección sobre Night Red; docs/THEMES.md también lo menciona).

Posibles problemas

  • Un color hardcodeado en el CSS es el error, no el tema. La auditoría solo verifica los tokens; un código como color: #fff en el código de la app permanece en blanco en cualquier tema. tools/lint_colors.py (en el repositorio) y la búsqueda mediante grep en AGENTS.md §8 detectan esto; el linter en CI no ejecuta esa fase, así que ejecútelo localmente antes de hacer merge.

  • ui-theme.js debe ser el primero en <head>, de forma clásica, no con atributos defer o module. Un script tipo módulo no dispone de document.currentScript, y el motor de ejecución lee sus propios atributos data-* desde esa etiqueta. El síntoma es un parpadeo donde primero se muestra el tema incorrecto y luego el correcto.

  • ui-theme.css debe cargarse después del CSS de la app, no antes. El orden correcto es: base, componentes, app, tokens. Una regla de la app con la misma especificidad que se carga después de los tokens queda anulada.

  • data-themes controla qué temas aparecen en el selector. Un tema almacenado cuyo identificador no esté en data-themes se ignora en la siguiente carga (el motor de ejecución recurre entonces al tema por defecto). Cuando elimine un tema, añada una vez data-legacy-key y data-legacy-map para que el valor almacenado se migre.

  • Los estilos rounded-md y font-sans de Tailwind cambian tras la instalación. Eso es normal: el tema define los tokens –radius- y –font-, cuyos valores prevalecen. No intente modificarlos.

  • Advertencia de hidratación en Next.js. Añada suppressHydrationWarning a <html> y silencie la regla de linter no-sync-scripts para el bloque head: el motor de ejecución establece atributos en ¿Qué significa todo esto para mí?

    Lo que quería era disponer de un sistema de temas real para todas las apps que desarrollo, sin tener que crear uno desde cero cada vez; ThemeForge es la versión de ese sistema que estoy dispuesto a mantener. Las carpetas que incorporo en las apps ahora se llaman ui-theme/ y el resto depende de la propia app; los cuatro tags del bloque head y el selector de temas son idénticos en cualquier framework. El agente encargado de la instalación lee AGENTS.md, no un mensaje de Slack. La auditoría de contraste, las pruebas del motor de ejecución mediante Chrome sin interfaz gráfica y el análisis node –check en cada archivo JS que se distribuye son los factores que me dan la confianza necesaria para seguir avanzando. Se encuentra en versión 1.0.0 porque los tokens constituyen la API pública, y el cambio de nombre de un token supone un cambio de versión mayor; cada lanzamiento se identifica mediante una etiqueta git, la carpeta VERSION refleja ese número y los archivos JSON se firman con la misma lista de checksums que update.py valida. La CI del propio repositorio arroja resultados positivos en Linux, Windows y Python 3.9; las mismas comprobaciones se cumplen al clonar el proyecto en esta máquina.

    Referencia (para agentes de IA)

    El resto de este artículo constituye la guía de referencia que un agente de programación (o mi futuro yo) puede copiar tal cual. La primera parte contiene texto narrativo; la segunda se estructura para facilitar su lectura por herramientas automáticas. A continuación encontrará cada token, cada clase de componente, cada método público en window.UITheme y window.UIComponents, todos los temas, cada parámetro configurable en las etiquetas script, cada adaptador, la ruta completa de instalación, el contrato de contraste y el bloque de versiones.

    Manifesto de archivos

    El repositorio contiene dos árboles esenciales: el paquete listo para usar que la app incorpora, y los materiales de diseño y herramientas que permiten generarlo. Este artículo se centra en el paquete.

    Paquete listo para usar — lo que la app copia (ui-theme/):

    Archivo Tamaño Líneas Descripción
    ui-theme.js 23,515 B 575 Motor de ejecución: aplica el tema guardado antes del primer renderizado, adapta el modo claro/oscuro según el SO mediante data-default="auto", rellena los selectores, sincroniza pestañas y expone window.UITheme
    ui-theme-base.css 13,255 B — Valores por defecto de elementos: texto del cuerpo, enlaces, títulos, código, anillo de foco, barras de desplazamiento, reducción de movimiento, niveles de texto, .ui-markdown, colores de highlight.js
    ui-components.css 51,344 B — Estilos para componentes: botones, campos, casillas, radios, interruptores, tarjetas, insignias, avisos, pestañas, controles segmentados, tablas, diálogos, menús, tooltips, notificaciones, progreso, bloques de código y estructura básica de la app
    ui-theme.css 86,389 B (21,197 B comprimido) — Tokens de los diez temas disponibles (aprox. 20 KB tras compresión)
    ui-components.js 5,441 B 135 Funciones opcionales con tematización: confirm(), alert(), prompt() y toast()
    ui-theme.d.ts 2,841 B — Declaraciones TypeScript para window.UITheme y window.UIComponents
    update.py 16,081 B — Instala y actualiza la carpeta; verifica cada archivo mediante SHA-256
    themes.json 4,089 B — Catálogo de temas (nombre, familia, base, conjunto, muestra visual, fuentes)
    files.json 1,401 B — Lista de checksums que update.py valida
    VERSION 30 B — Versión del paquete (ThemeForge 1.0.0 3db64d9f574f)
    README.md 6,342 B — Instrucciones de uso específicas para el paquete
    adapters/quasar.css 24,997 B — Mapeo para NiceGUI/Quasar
    adapters/quasar.js 1,468 B 40 Puente JavaScript para NiceGUI/Quasar
    adapters/tailwind.css 4,399 B — Mapeo @theme inline de Tailwind CSS v4
    adapters/tailwind-v3.preset.js 2,915 B 54 Preset para Tailwind CSS v3

    Materiales de diseño y herramientas (no se copian en la app):

    Archivo Tamaño Descripción
    README.md 6,592 B Información general del repositorio
    AGENTS.md 19,063 B Guía detallada para la instalación, destinada a agentes de IA
    CHANGELOG.md 4,425 B Historial de versiones (1.0.0 es el primer lanzamiento)
    CLAUDE.md 1,498 B Normas específicas para Claude en este repositorio
    CONTRIBUTING.md 4,476 B Cómo colaborar en el desarrollo de los temas
    LICENSE 1,067 B Licencia MIT; copyright © 2026. El archivo original cita al autor por su nombre personal; la marca comercial utilizada en el sitio web es distinta, y el texto que figura en disco coincide con el de la licencia original. No se incluye en el zip de descarga, ya que la línea de copyright del archivo original revela la identidad del autor, lo cual el sistema de protección de contenidos del sitio considera información sensible.
    docs/TOKENS.md 15,391 B Descripción detallada de cada token, agrupado por categorías
    docs/COMPONENTS.md 13,889 B Cada clase de componente, acompañada de ejemplos de código
    docs/THEMES.md 8,081 B Información sobre los temas, su diseño y cómo crear uno nuevo
    docs/INTEGRATIONS.md 10,604 B Instrucciones específicas para integrar el paquete en distintos frameworks
    docs/TEXT.md 5,465 B Niveles de texto y formato Markdown predeterminado
    docs/UPDATING.md 4,134 B Procedimientos de actualización, uso de caché y significado de los checksums
    docs/contrast-report.md 124,372 B Resultados de la auditoría de contraste (10 temas × entre 147 y 171 filas)
    docs/theme-template.css 9,854 B Plantilla básica para crear nuevos temas mediante tools/sync_theme.py
    tokens/<theme>.json ~57 KB cada uno Tokens resultantes de cada tema, en formato JSON DTCG W3C
    examples/static-html/ 3,731 B index Ejemplo sencillo con HTML, CSS y JS puro
    examples/fastapi-jinja/ 2,172 B app.py Ejemplo de integración con FastAPI y Jinja
    specimen/index.html 17,721 B Visualización local de todos los componentes en cada tema
    tools/check_contrast.py 43,171 B Herramienta de auditoría de contraste (ejecutada en CI)
    tools/lint_colors.py 22,711 B Detecta valores de color hardcodeados en el CSS de la app
    tools/sync_theme.py 41,671 B Genera ui-theme.css, los archivos tokens/*.json y docs/contrast-report.md a partir de src/css/*.css
    tools/update.py 16,081 B Script de instalación y verificación (equivalente a ui-theme/update.py)
    tools/screenshots.py 3,273 B Genera capturas de pantalla de los temas para docs/images/
    tests/test_tools.py 17,606 B Pruebas unitarias en Python (32 ejecutadas; 1 omitida en esta clonación)
    tests/run_browser_tests.py 3,570 B Ejecuta pruebas del motor de ejecución mediante Chrome sin interfaz gráfica
    tests/runtime.html 24,930 B Código base para las pruebas del navegador
    .github/workflows/ci.yml — Configuración CI: contraste, node --check, pruebas unitarias y de navegador, verificación de formato CRLF; ejecutada en Linux, Windows y Python 3.9

    La CI del repositorio ejecuta tres tareas: checks en Ubuntu con Python 3.12, tools-on-windows en Windows con Python 3.11 y updater-on-oldest-python en Ubuntu con Python 3.9. La clonación local supera satisfactoriamente la validación node –check en todos los archivos JavaScript distribuidos; el analizador de contraste reproduce fielmente las diez filas de datos de la auditoría, y todas las pruebas unitarias arrojan éxito (32 superadas, 1 omitida en 1.212 s en Linux con Python 3.14, fecha 05/10/2026).

    Tokens de diseño (grupos, función, valor de ejemplo)

    Cada tema define todos los tokens. Los valores que se indican a continuación corresponden al tema Púrpura (la base :root); los demás temas disponen de sus propios valores definidos en tokens/<theme>.json (formato JSON DTCG). Para utilizarlos, emplee la sintaxis var(--nombre). Jamás vuelva a declarar un token en el CSS de la app: asigne a sus variables un prefijo propio (--myapp-sidebar-w) o cree un alias al token (--myapp-brand: var(--accent)). Fuente: docs/TOKENS.md.

    Grupo Token Rol Ejemplo (púrpura)
    Superficies --surface-void más oscuro que la página (cubre todo el ancho) #08080f
    Superficies --surface-0 la página #0e0e1b
    Superficies --surface-1 navegación #14142a
    Superficies --surface-2 tarjetas #1d1d39
    Superficies --surface-3 estado de hover #232342
    Superficies --surface-4 estado activo #262648
    Superficies --surface-sunken zonas hundidas #0a0a14
    Superficies --surface-overlay menús, popovers #1d1d39
    Superficies --glass-1/2/3 paneles translúcidos rgba(29,29,57,.72/.84/.92)
    Superficies --glass-highlight brillo del vidrio rgba(255,255,255,.055)
    Superficies --code-bg fondo de código #0b0b16
    Texto --text-primary texto principal #e8e8f0
    Texto --text-secondary etiquetas, descripciones #a0a0bd
    Texto --text-tertiary pistas, marcas de tiempo #8d8db0
    Texto --text-disabled controles deshabilitados #717195
    Texto --text-inverse texto sobre un fondo claro #0e0e1b
    Texto --text-link / --text-link-hover enlaces y texto de acento #a78bfa / #c4b5fd
    Texto --on-accent / --on-danger / --on-success / --on-warning / --on-media / --on-media-muted etiqueta sobre un fondo #ffffff / #2a0808 / …
    Acento --accent / --accent-hover / --accent-pressed acento de marca, acciones principales #7c3aed / #8250f0 / #6d28d9
    Acento --accent-subtle / --accent-muted / --accent-glow fondo teñido, relleno suave, brillo rgba(124,58,237,.16/.26/.35)
    Acento --accent-rgb permite a JS componer rgba(var(--accent-rgb), .2) 124,58,237
    Acento --accent-2 / --accent-2-subtle acento secundario #5eead4
    CTA --cta / --cta-hover / --cta-pressed / --on-cta botón de acción destacada #7c3aed / #8250f0 / #6d28d9 / #ffffff
    CTA --cta-shadow / --cta-shadow-hover sombras para el botón 0 6px 20px rgba(124,58,237,.28) / .38
    CTA --highlight / --highlight-subtle / --on-highlight marcas, color de sugerencias #fcd34d / rgba(252,211,77,.12) / #251a00
    Líneas --border-subtle / --border / --border-strong los bordes de los controles usan --border-strong con una relación de 3:1 #21213b / #292945 / #6f6f9c
    Líneas --divider líneas finas #21213b
    Líneas --focus-ring / --focus-ring-width / --focus-ring-offset anillo de enfoque #a78bfa / 2px / 2px
    Líneas --glass-stroke / --glass-stroke-strong bordes de vidrio rgba(255,255,255,.08/.16)
    Estados de control --selected / --on-selected activado/marcado/presionado/actual según el tema
    Estados de control --unselected-border / --unselected-fg contorno desactivado; relación de 3:1 en todas las superficies según el tema
    Estado --success / --warning / --danger / --info puntos, barras, rellenos según el tema
    Estado --success-text / --warning-text / --danger-text / --info-text color del texto para cada estado según el tema
    Estado --success-subtle / --warning-subtle / --danger-subtle / --info-subtle fondo teñido para cada estado según el tema
    Estado --success-border / --warning-border / --danger-border / --info-border bordes de estado según el tema
    Estado --idle / --idle-text / --idle-subtle / --idle-border / --idle-hover estado neutro según el tema
    Estado --live / --live-text / --live-subtle / --live-border / --live-hover indicador de “en ejecución” según el tema
    Código/sintaxis --syn-bg / --syn-fg / --syn-comment / --syn-keyword / --syn-string / --syn-number / --syn-function / --syn-attr / --syn-tag / --syn-builtin / --syn-type / --syn-variable / --syn-literal / --syn-operator / --syn-title / --syn-addition escala de resaltado sintáctico según el tema
    Código/sintaxis --code-header-bg / --code-stroke marco de bloques de código (oscuro en todos los temas) según el tema
    Gráficos --cat-1 … --cat-12 colores para series; relación de 3:1 respecto a --surface-0 según el tema
    Gráficos --seq-1 … --seq-5 escala de bajo a alto según el tema
    Gráficos --div-1 … --div-5 malo, neutro, bueno según el tema
    Gráficos --chart-grid / --chart-axis elementos gráficos según el tema
    Burbujas --bubble-user-text / --bubble-assistant-text / --bubble-user-bg / --bubble-assistant-bg burbujas de chat según el tema
    Burbujas --rp-speech / --rp-thought / --rp-shout / --rp-whisper / --rp-ooc / --rp-action / --rp-critical colores para burbujas de rol según el tema
    Diferencias --diff-add-bg / --diff-add-text / --diff-remove-bg / --diff-remove-text vista de diferencias según el tema
    Tipografía --fs-xs / --fs-sm / --fs-md / --fs-lg / --fs-xl / --fs-2xl tamaños de fuente según el tema
    Tipografía --fw-medium / --fw-semibold / --fw-bold pesos de fuente según el tema
    Tipografía --font-sans / --font-mono / --font-display familias tipográficas según el tema
    Espaciado --space-1 … --space-8 4–64 px según el tema
    Radio --radius-sm / --radius-md / --radius-lg / --radius-pill formas de los controles según el tema
    Sombras --shadow-1 / --shadow-2 / --shadow-3 / --shadow-4 niveles de sombra según el tema
    Capas Z --z-modal / --z-toast / --z-popover / --z-nav orden de apilamiento según el tema
    Movimiento --motion-fast / --motion-med / --motion-slow / --easing-standard tiempos de animación (el modo “reducción de movimiento” detiene los bucles) según el tema
    Markdown --md-bold / --md-italic / --md-bolditalic / --md-bolditalic-glow formato Markdown en la app según el tema
    Misceláneos --mark-bg / --selection-text / --selection-bg / --media-filter / --quote-bar / --heartbeat-text / --heartbeat-hover / --offline-text / --on-offline / --canvas-handle características menores según el tema

    Fuente: docs/TOKENS.md (22 grupos, ~270 tokens; el comando grep -oE '\| \(–[a-zA-Z][a-zA-Z0-9-]*)` |’ docs/TOKENS.md | sort -u | wc -ldevuelve 272 nombres de token únicos; hay 22 grupos marcados con## `).

    Clases de componentes (cada modificador, una línea)

    El estado se determina a partir de atributos nativos (disabled, checked, aria-pressed, aria-selected, aria-current, aria-invalid, aria-busy, [open]); nunca se usa una clase adicional. La mayoría de los selectores constan de una sola clase, de modo que cualquier regla posterior con la misma especificidad en la aplicación prevalece. Se emplean propiedades lógicas en todo el código (funcionan correctamente en dirección derecha-izquierda). Los estados “on”, “checked”, “pressed” y “current” se representan mediante --selected; el estado “off” se indica con un contorno; los elementos deshabilitados tienen un borde discontinuo y no se rellenan. Fuente: docs/COMPONENTS.md.

    Clase Modificadores / partes Descripción
    ui-stack — Columna; el espaciado entre elementos es --space-3
    ui-row — Fila que se ajusta automáticamente; centrada, con separación --space-2
    ui-grid --ui-grid-min Genera columnas automáticamente; el valor min se establece en el elemento
    ui-container — Centrado; ancho máximo definido por --content-max
    ui-spacer — Empuja el resto de los elementos de una fila hacia el final
    ui-app __header __nav __main Estructura base de la app (encabezado, navegación lateral, contenido principal); la navegación se oculta por debajo de 760 px
    ui-brand — Título de la app en el encabezado
    ui-nav __label __item Navegación lateral
    ui-title / ui-heading / ui-subheading / ui-lead / ui-kicker / ui-small / ui-mono / ui-num / ui-kbd / ui-code / ui-divider — Jerarquía tipográfica (<hr> equivale a .ui-divider)
    ui-text-primary / -secondary / -tertiary / -disabled / -link — Clases para distintos niveles de texto (para código nuevo, se recomienda usar los tokens)
    ui-markdown — Contenedor para Markdown renderizado; véase docs/TEXT.md
    ui-btn --primary --ghost --outline --danger --cta --sm --lg --icon --block Botones; también funcionan con <a>; se integran con aria-pressed / aria-busy / disabled
    ui-btn-group — Botones adyacentes comparten bordes redondeados
    ui-field — Contenedor de campo de formulario (etiqueta + control + ayuda)
    ui-label — Etiqueta del campo
    ui-input --sm Campo de texto
    ui-select — <select> con estilo personalizado; data-ui-theme-picker permite cargar el selector de temas
    ui-textarea — <textarea> con estilo personalizado
    ui-help — Texto de ayuda del campo (enlaza a aria-describedby)
    ui-error — Mensaje de error del campo (enlaza a aria-describedby); se muestra cuando aria-invalid="true"
    ui-input-group — Combinación de input + botón (p. ej. para búsquedas)
    ui-check — Fila con checkbox, radio o interruptor
    ui-checkbox — <input type="checkbox"> con estilo personalizado
    ui-radio — <input type="radio"> con estilo personalizado
    ui-switch — Checkbox con role="switch" que se muestra como interruptor
    ui-switch-state data-on data-off Etiquetas “On”/“Off” (ocultas a lectores de pantalla; el propio interruptor anuncia su estado)
    ui-range — Control deslizante cuyo color se define mediante --slider-color
    ui-segmented — Grupo de botones que actúan como radio buttons
    ui-tabs ui-tab Lista de pestañas (las pestañas enlazadas usan <a aria-current="page">; la gestión del teclado es responsabilidad de la app)
    ui-card __header __title __footer --raised --interactive Tarjeta; aria-selected / aria-current indican una tarjeta seleccionada
    ui-well — Zona hundida (para logs, previsualizaciones, contenido secundario)
    ui-stat __label __value Par etiqueta/valor
    ui-badge --success --warning --danger --info --live --accent --neutral Etiqueta en forma de píldora
    ui-dot --success --warning --danger --info --live --neutral Punto de estado
    ui-count --accent --danger Chip contador
    ui-callout --info --success --warning --danger __title Bloque informativo coloreado (para errores, use role="alert")
    ui-table-wrap — Envuelve <table class="ui-table"> para permitir encabezados fijos y desplazamiento
    ui-table --hover --compact td.num Estilos de tabla
    ui-dialog — <dialog> con estilo personalizado
    ui-drawer — Panel lateral basado en <dialog>
    ui-menu __item Lista de menú
    [data-ui-tooltip] data-ui-tooltip-side="bottom" Tooltip en cualquier elemento
    ui-progress — Barra de progreso lineal
    ui-spinner — Indicador de carga
    ui-skeleton — Esqueleto de carga
    ui-breadcrumbs — Lista de ruta de navegación
    ui-pagination — Paginación
    ui-avatar — Avatar circular
    ui-chip __remove Chip eliminable o seleccionable
    ui-details — Acordeón basado en <details>
    ui-fieldset — Grupo de campos con leyenda
    ui-codeblock __bar <figure> que contiene <figcaption class="ui-codeblock__bar"> y <pre>
    ui-empty — Estado vacío
    ui-bubble --user --assistant Burbuja de chat

    Métodos públicos en window.UITheme y window.UIComponents

    Fuente: ui-theme/ui-theme.d.ts (declaraciones TypeScript para ambos objetos globales).

    window.UITheme (UIThemeApi):

    Miembro Tipo Función
    version string (solo lectura) Versión de la carpeta, p. ej. "1.0.0"
    config objeto (solo lectura) { themes, default, auto, storageKey, families, printTheme }
    current() () => string El slug del tema activo
    theme([slug]) (slug?) => UIThemeInfo \| null Información sobre un tema (o el activo)
    list() () => UIThemeInfo[] Todos los temas habilitados
    set(slug) (slug) => string Cambia a un tema; devuelve el slug
    reset() () => string Vuelve al tema predeterminado; devuelve el slug
    partner([slug]) (slug?) => string \| null El tema claro/oscuro correspondiente en una familia (p. ej. laserlloyd ↔ laserlloyd-light)
    toggleFamily() () => string \| null Cambia al tema complementario; devuelve el nuevo slug
    onChange(listener) (fn) => () => void Permite suscribirse; devuelve una función para darse de baja. detail.print es true en cambios relacionados con la impresión
    token(name, [el]) (name, element?) => string Valor crudo del token (p. ej. "#7c3aed")
    tokens(names, [el]) (names, element?) => Record<name, string> Varios tokens a la vez
    color(name) (name) => string Color resuelto en formato rgb() para el lienzo
    colors(names) (names) => Record<name, string> Varios colores resueltos para el lienzo
    mountPicker(target, [opts]) (elOrSel, options?) => HTMLSelectElement \| null Rellena un select como selector; options son { label, coreLabel, optInLabel, systemLabel }

    El evento ui-theme-change se dispara en document con { slug, theme, previous, print }.

    window.UIComponents (UIComponentsApi): (requiere ui-components.js)

    Método Firma Función
    confirm (opts: UIDialogOptions \| string) => Promise<boolean> confirm() con temática; las opciones son { title, message, label, confirmLabel, cancelLabel, danger }
    alert (opts: UIDialogOptions \| string) => Promise<void> alert() con temática
    prompt (opts: UIPromptOptions \| string) => Promise<string \| null> prompt() con temática; devuelve null si se cancela. Opciones adicionales: { value, placeholder, type }
    toast (message, { kind?, timeout? }) => HTMLElement Notificación con tipo info / success / warning / danger; devuelve el elemento

    window.UI_THEME_MANIFEST (opcional; tiene prioridad sobre los valores por defecto): { themes, default, defaultDark, defaultLight, storageKey, families, legacy, mirrorAttr, fontsHref, printTheme }. themes acepta un array o una cadena separada por comas.

    Parámetros del tag <script> (data-* en el tag <script>)

    Atributo Valor por defecto Función
    data-themes los seis temas principales (purple,midnight-gold,glacier,forest,paper,daylight) Lista separada por comas de los temas habilitados; controla el selector y qué valores almacenados se respetan. Si no se define data-themes, ui-theme.js habilita los seis temas con set==="core" (ui-theme.js:147-149).
    data-default el primer tema habilitado (el primer slug en data-themes, o purple si no hay ninguno habilitado y no es auto) El slug del tema predeterminado, o auto para seguir la configuración del sistema operativo. La cadena literal auto activa el seguimiento mediante prefers-color-scheme (ui-theme.js:164); si el atributo está ausente/vacío, se usa el primer tema habilitado (ui-theme.js:177-179).
    data-default-dark el primer tema no claro habilitado (el primer slug en data-themes cuyo ground !== "light", o el primero si no hay ninguno; de lo contrario, purple) La versión oscura cuando se usa auto. ui-theme.js:168-175 lo selecciona cuando el sistema prefiere modo oscuro y no hay valor explícito.
    data-default-light el primer tema claro habilitado (el primer slug en data-themes cuyo ground === "light", o el primero si no hay ninguno; de lo contrario, purple) La versión clara cuando se usa auto. Usa el mismo código (ui-theme.js:168-175).
    data-storage-key ui-theme Clave de localStorage donde se guarda la elección del usuario (ui-theme.js:185). AGENTS.md §3 recomienda usar <appname>.theme para evitar conflictos entre varias apps ThemeForge en el mismo origen.
    data-families false Agrupa los temas por familia en el selector
    data-print-theme auto Qué tema se usa al imprimir: si el tema activo es oscuro u OLED, auto cambia a la versión clara de la familia (o al primer tema claro habilitado, o daylight); un slug específico imprime ese tema; none no hace cambios; si el tema activo es claro, se imprime tal cual (ui-theme.js:474-490).
    data-legacy-key — Clave de almacenamiento antigua para migrar una sola vez (con data-legacy-map)
    data-legacy-map — Mapa de→a para valores heredados (objeto JSON)
    data-mirror-attr — Copia el tema activo a otro atributo (para librerías que lo lean)
    data-fonts-href — URL de una hoja de estilo con las fuentes del tema

    Fuente: ui-theme.js:147-149, 164, 168-174, 185, 474-490 (valores por defecto en tiempo de ejecución) y AGENTS.md §3, §12 (sobrescrituras recomendadas; p. ej. definir data-themes con los seis temas principales, data-default="auto", data-storage-key="<appname>.theme").

    Adaptadores

    Adaptador Archivos Función
    NiceGUI / Quasar adapters/quasar.js + adapters/quasar.css Cargue adapters/quasar.js justo después de ui-theme.js y adapters/quasar.css tras ui-theme.css (mediante ui.add_head_html). Los toggles, checkboxes y radios de Quasar usan el diseño de estado de control; los controles deshabilitados se muestran con trazos y opacidad total. Elimine cualquier llamada a ui.dark_mode(); el adaptador lo gestiona.
    Tailwind CSS v4 adapters/tailwind.css @import "./<path>/ui-theme/adapters/tailwind.css"; después de @import "tailwindcss";. Expone bg-surface-2, text-fg, text-fg-muted, bg-accent, text-on-accent, border-line, etc. El texto usa fg-* porque los tamaños text-* pertenecen a Tailwind.
    Tailwind CSS v3 adapters/tailwind-v3.preset.js presets: [require('./<path>/ui-theme/adapters/tailwind-v3.preset.js')]. Contiene los mismos tokens que el adaptador v4, expresados como preset v3.

    El adaptador de Tailwind mapea los tokens del tema; el de Quasar mapea las clases de componentes. Ninguno es obligatorio para que el resto del paquete funcione.

    Ruta completa de instalación (texto literal, sección de instalación de AGENTS.md)

    AGENTS.md es el script de instalación en formato de texto, pensado para agentes de codificación IA. A continuación se transcriben íntegramente las dos primeras secciones; este es el prompt al que se apunta a un agente IA. Los caracteres se escapan según la regla §8 de Article-Forge (un <blockquote> crudo ejecuta markdown literalmente, por lo que <, >, & se escapan como &lt;, &gt;, &amp;).

    ## 1. Decida una vez
    
    | Pregunta | Respuesta por defecto |
    |---|---|
    | ¿Dónde va la carpeta? | En la carpeta estática de la app, servida tal cual: `static/ui-theme/` (Flask, FastAPI, Django), `public/ui-theme/` (Vite, Next.js, Create React App), `app/static/ui-theme/` o junto a `index.html` en sitios simples. |
    | ¿Qué temas? | Los seis temas principales: `purple,midnight-gold,glacier,forest,paper,daylight`. Añada algún tema optativo (`night-red`, `electric-yellow`, `laserlloyd`, `laserlloyd-light`) solo si el usuario lo solicita. |
    | ¿Tema predeterminado? | `auto`: sigue la configuración de claro/oscuro del sistema hasta que el usuario elija uno (`data-default-dark="midnight-gold"`, `data-default-light="daylight"`). |
    | ¿Clave de almacenamiento? | `<appname>.theme`, p. ej. `notes.theme`. |
    
    ## 2. Instale
    
    Ejecute desde la carpeta raíz de la app (Python 3.9 o superior; cambie `static/ui-theme` por la carpeta elegida):
    
    
    
    python3 -c &quot;import urllib.request as u,sys;sys.argv=['update.py','--dest','static/ui-theme'];exec(u.urlopen('https://raw.githubusercontent.com/LaserLloyd/ThemeForge/main/ui-theme/update.py').read())&quot;
    
    En Windows use `python` (o `py`) en vez de `python3`; la línea es idéntica en PowerShell, cmd y bash. Descarga el instalador, que obtiene la última versión desde GitHub, verifica cada archivo contra su lista de checksums y crea la carpeta. Para actualizaciones posteriores: `python3 static/ui-theme/update.py`. Sin conexión: descargue un archivo comprimido (`.tar.gz`) en otro lugar y ejecute `python3 update.py --source <archive> --dest static/ui-theme` usando el `update.py` de la carpeta `ui-theme/`. Otras formas, si Python no está disponible: - **git:** `git clone --depth 1 https://github.com/LaserLloyd/ThemeForge.git ut-tmp`, copie `ut-tmp/ui-theme` a la app y elimine `ut-tmp`. - **Node:** `npx degit LaserLloyd/ThemeForge/ui-theme#v1.0.0 static/ui-theme`. - **Sin instalación (prototipos, archivos HTML simples):** cargue los archivos desde jsDelivr, fijados a una versión: `https://cdn.jsdelivr.net/gh/LaserLloyd/ThemeForge@v1.0.0/ui-theme/ui-theme.js` (y la misma ruta para cada archivo CSS). Nunca use `@main`; el CDN lo cachea hasta 12 horas. Para actualizar una página CDN, cambie la versión fijada; los pasos 8.5, 9 y 10 no se aplican a ella.

    El resto de AGENTS.md (secciones 3–12) trata el bloque head, el selector, cómo generar desde tokens, reglas, gráficos, verificación, la línea que debe incluirse en el propio AGENTS.md de la app para mantener la convención entre agentes, el comando de actualización, la tabla de solución de problemas y la lista de referencia anterior.

    Auditoría de contraste (resumen, todos los temas)

    tools/check_contrast.py se ejecuta en CI con cada push. El informe completo ocupa 124 KB (una sección por tema más un resumen) en docs/contrast-report.md; el resumen es:

    Tema Conjunto Perfil Comprobaciones Fallos
    purple core estándar 147 0
    midnight-gold core estándar 147 0
    glacier core estándar 147 0
    forest core estándar 147 0
    paper core estándar 147 0
    daylight core estándar 147 0
    electric-yellow opt-in estándar 147 0
    laserlloyd opt-in estándar 147 0
    laserlloyd-light opt-in estándar 147 0
    night-red opt-in noche 171 0

    El contrato que todo tema debe cumplir: texto principal 7:1, texto secundario 6:1 (el informe de contraste señala “la promesa de 6:1 del contrato” — docs/contrast-report.md marca cada fila text-secondary on surface-2 con esa frase exacta), cualquier nivel de texto sobre cualquier superficie 4.5:1, deshabilitado 3:1, sobre-accent y sobre-estado 4.5:1, texto de estado sobre su fondo teñido 4.5:1, sobre-seleccionado 4.5:1, seleccionado / borde-no-seleccionado / fg-no-seleccionado en cualquier superficie 3:1, borde-fuerte / pista-de-control / anillo-de-enfoque 3:1, colores de sintaxis sobre --syn-bg 4.5:1 (los comentarios 3.5:1). Activado/desactivado por forma: un control “activado” se rellena con --selected; uno “desactivado” es un contorno en --unselected-border; en un interruptor, el estado “on” añade una barra al botón y “off” un anillo. Deshabilitado aparece como trazo sin relleno en el nivel deshabilitado, incluso si está activado.

    Frameworks

    Según docs/INTEGRATIONS.md: HTML plano · FastAPI, Flask, Starlette (plantillas Jinja) · Django · Vite, Vue, Svelte, SvelteKit, Astro · Next.js (router de app) · NiceGUI (Quasar) · Tailwind CSS · Electron, Tauri, pywebview · Fuentes · Gráficos · Política de seguridad de contenidos. Por framework: coloque ui-theme/ donde el framework sirva archivos estáticos, añada el bloque head en el orden indicado en AGENTS.md §3 y sirva la carpeta sin cachear (o versione las URLs) para que las actualizaciones se reflejen. El repositorio incluye dos ejemplos concretos: examples/static-html/ (una página única) y examples/fastapi-jinja/ (FastAPI + Jinja, con un app.py de 2,172 bytes).

    Impresión, contraste y animación

    Tres elementos que el motor detecta y el CSS responde sin necesidad de banderas temáticas:

    • Impresión — data-print-theme controla qué tema se imprime (ui-theme.js:474-490): cuando el tema activo es oscuro u OLED, auto cambia automáticamente al tema claro correspondiente (o al primer tema claro habilitado, o a daylight); si se indica un nombre específico, se imprime ese tema; none evita cualquier cambio. Cuando el tema activo es claro, la página se imprime tal como está. La función de impresión oculta la barra lateral de navegación, los mensajes emergentes, menús, cajones y tooltips.

    • prefers-contrast: more — todos los temas aumentan el grosor de las líneas hasta alcanzar el nivel máximo permitido, y elevan el texto terciario al nivel secundario.

    • prefers-reduced-motion — detiene los bucles animados y acorta la duración de las animaciones; los tokens --motion-* pasan a tener valor 0.

    Versiones

    Según el repositorio en la versión actual descrita en este artículo (clonado el 05-10-2026):

    $ git log -1 --format='%h %ci'
    56fb665 2026-10-05 21:46:52 +0900        # ThemeForge 1.0.0
    
    $ cat ui-theme/VERSION
    ThemeForge 1.0.0 3db64d9f574f
    
    $ wc -c ui-theme/*.js ui-theme/*.css ui-theme/*.ts ui-theme/*.py 2>/dev/null
      23515 ui-theme.js
       5441 ui-components.js
       2841 ui-theme.d.ts
      16081 update.py
      13255 ui-theme-base.css
      51344 ui-components.css
      86389 ui-theme.css
    
    $ node --check ui-theme.js ui-components.js
    (node v24.18.0) — Todo correcto en ambos archivos, así como en adapters/quasar.js y adapters/tailwind-v3.preset.js
    
    $ python -m unittest discover -s tests
    Se ejecutaron 32 pruebas en 1.212 segundos.
    OK (omitidas=1)
    
    $ python tools/check_contrast.py --fail-on any
    …
    ## Resumen
    | Tema | Conjunto | Perfil | Pruebas | Fallos |
    | purple | core | standard | 147 | 0 |
    | midnight-gold | core | standard | 147 | 0 |
    | glacier | core | standard | 147 | 0 |
    | forest | core | standard | 147 | 0 |
    | paper | core | standard | 147 | 0 |
    | daylight | core | standard | 147 | 0 |
    | electric-yellow | opt-in | standard | 147 | 0 |
    | laserlloyd | opt-in | standard | 147 | 0 |
    | laserlloyd-light | opt-in | standard | 147 | 0 |
    | night-red | opt-in | night | 171 | 0 |
    

    Compatibilidad: Chrome, Edge, Firefox y Safari actuales (2024 o posteriores). Esta capa utiliza :has(), color-mix() y la API de popovers; los navegadores antiguos mantienen los colores, pero algunos estados de componentes y menús podrían mostrarse de forma degradada.

    Relacionado: ChatForge: un asistente de IA local basado en NPU para la Copilot Key · StudioForge: un servidor LLM exclusivo para GPU · DisPatch: chat de IA autoalojado · Mi pila de agentes de IA local · Cómo hacer que una IA adapte cualquier proyecto a su sistema

    Descargas

    Gratis para uso personal. Si te ahorra una tarde, el botón del café está aquí cerca.


← Más de IA y LLM Local