CubicLauncher permite personalizar la interfaz de usuario mediante themes (temas). Un theme define colores, fuentes, bordes, sombras, imágenes de fondo, iconos y, en el formato V2, hojas de estilo CSS adicionales.
Esta guía describe cómo crear un theme desde cero, cómo empaquetarlo, cómo probarlo localmente y cómo publicarlo en el repositorio oficial.
Actualizada al commit 5a7e752 de develop (16 de septiembre de 2026). Las nuevas medidas y la prioridad de Inject.css requieren una compilación que incluya ese cambio. Consultá las variables predeterminadas en reset.css como referencia de nombres y valores.
Introduccióneditar
¿Qué es un theme?editar
Un theme es un conjunto de archivos que CubicLauncher interpreta para modificar la apariencia visual de la aplicación. Internamente, CubicLauncher convierte cualquier formato de theme a una estructura común llamada ThemeResponse, que el frontend utiliza para aplicar los estilos.
Versiones del formatoeditar
CubicLauncher soporta dos versiones del formato de themes:
| Versión | Formato | Estado | Recomendación |
|---|---|---|---|
| V1 | JSON (theme.json) | Legacy | Se mantiene por compatibilidad, pero no recibe nuevas funciones. |
| V2 | TOML (Meta.toml + Definition.toml) | Actual | Se recomienda para themes nuevos. Soporta iconos, CSS inyectado y una organización más clara. |
Conceptos generaleseditar
Detección de versioneseditar
CubicLauncher detecta automáticamente la versión del theme según el archivo presente en el directorio del tema:
- Si existe
Meta.toml, se trata de un V2. - Si existe
theme.json, se trata de un V1.
Al importar un ZIP mediante import_theme_zip, CubicLauncher primero busca un theme.json dentro del paquete. Si no lo encuentra, intenta importar el archivo como un paquete V2 (Meta.toml).
Resolución de rutaseditar
Las rutas relativas especificadas en imágenes de fondo, fuentes e iconos se resuelven automáticamente respecto al directorio del theme instalado. Se recomienda usar rutas relativas dentro del ZIP para mantener el paquete portable.
Validaciones de recursoseditar
CubicLauncher aplica las siguientes validaciones de seguridad:
- Imágenes de fondo: deben ser archivos de imagen válidos (identificación por magic bytes) y no pueden superar los 25 MB.
- Iconos personalizados (V2): deben tener extensión
svg,png,webp,jpgojpeg; las imágenes rasterizadas no pueden superar los 2 MB. - Fuentes: si la ruta es relativa, se resuelve localmente al directorio del theme.
Crear un theme V1 (legacy)editar
El formato V1 utiliza un único archivo JSON llamado theme.json. Es simple pero limitado: no soporta iconos personalizados ni CSS inyectado.
El repositorio oficial de Themes ya no acepta envíos en formato legacy V1 (theme.json). Este formato se mantiene solo por compatibilidad en el launcher. Para crear y publicar nuevos themes, usá el formato V2 en TOML: Meta.toml + Definition.toml.
Archivos requeridoseditar
NombreDelTheme/
└── theme.json # obligatorioRecursos opcionaleseditar
bg.EXT— imagen de fondo.- Archivos de fuentes referenciados en
fonts.
Schema de theme.jsoneditar
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name | string | Sí | Nombre del theme. |
author | string | No | Autor del theme. |
version | string | No | Versión del theme (se recomienda semver). |
type | string | No | Tipo del theme. Se expone tal cual en el listado. |
variables | objeto | Sí | Mapa de variables CSS clave: valor. |
bg_image | string | No | Ruta de la imagen de fondo. |
bg_image_blur | string | No | Desenfoque de la imagen de fondo. Se convierte a número si es posible. |
bg_image_opacity | number | No | Opacidad de la imagen de fondo (0.0 a 1.0). |
fonts | array | No | Lista de fuentes personalizadas. |
Fuentes en V1editar
Cada entrada del array fonts sigue este schema:
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
family | string | Sí | Nombre de la familia tipográfica. |
src | string | Sí | Ruta al archivo de la fuente. |
format | string | No | Formato de la fuente, por ejemplo woff2. |
weight | string | No | Peso de la fuente, por ejemplo 400 o 700. |
style | string | No | Estilo de la fuente, por ejemplo normal o italic. |
Ejemplo completo V1editar
{
"name": "Midnight Blue",
"author": "CubicLabs",
"version": "1.0.0",
"type": "user",
"variables": {
"--bg-main": "#0a0e17",
"--bg-card": "#111827",
"--accent": "#3b82f6",
"--text-primary": "#e5e7eb",
"--border-radius": "8px"
},
"bg_image": "bg.webp",
"bg_image_blur": "8",
"bg_image_opacity": 0.4,
"fonts": [
{
"family": "Inter",
"src": "fonts/Inter.woff2",
"format": "woff2",
"weight": "400"
}
]
}Limitaciones de V1editar
- No incluye sistema de iconos personalizados.
- No permite inyectar CSS adicional.
- El campo
bg_image_blurse recibe comostringy se intenta parsear a número. - Las variables CSS se definen manualmente tal cual serán aplicadas.
Crear un theme V2 (recomendado)editar
El formato V2 separa los metadatos de las definiciones visuales en dos archivos TOML:
Meta.toml: información del autor, nombre, versión y si el theme inyecta CSS.Definition.toml: todas las variables visuales, fuentes, iconos, fondos y valores adicionales.
Archivos requeridoseditar
NombreDelTheme/
├── Meta.toml # metadatos
└── Definition.toml # definiciones visualesRecursos opcionaleseditar
Inject.css— hoja de estilos adicional.bg.EXT— imagen de fondo.- Archivos de fuentes.
- Iconos SVG/PNG/WEBP/JPG organizados en subcarpetas.
Schema de Meta.tomleditar
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name | string | Sí | Nombre del theme. |
author | string | No | Autor del theme. |
version | string | No | Versión del theme (se recomienda semver). |
description | string | No | Descripción breve del theme. |
injects_css | boolean | No | Indica si el theme incluye un archivo Inject.css. |
Schema de Definition.tomleditar
| Campo | Tipo | Descripción |
|---|---|---|
[background] | sección | Configuración de la imagen de fondo. |
[background.reference_path] | string | Ruta de la imagen de fondo. |
[background.image_blur] | number | Desenfoque de la imagen. |
[background.image_opacity] | number | Opacidad de la imagen (0.0 a 1.0). |
[colors] | objeto | Colores del theme. |
[text] | objeto | Colores y estilos de texto. |
[borders] | objeto | Bordes y radios. |
[layout] | objeto | Espaciados, anchos, alturas y demás valores de layout. |
[shadows] | objeto | Sombras y glows. |
[backgrounds] | objeto | Colores de fondo adicionales. |
[backdrop] | objeto | Valores de desenfoque de fondo (backdrop blur), en píxeles. |
[fonts] | array | Fuentes personalizadas. |
[icons] | sección | Iconos personalizados. |
[icons.preview] | string | Icono de vista previa del theme. |
[icons.<grupo>] | objeto | Iconos agrupados por categoría. |
[others] | objeto | Variables adicionales libres. |
Sistema de prefijos de variables CSSeditar
En V2, CubicLauncher convierte automáticamente las secciones del TOML en variables CSS planas que el frontend puede consumir. La siguiente tabla muestra el prefijo que se aplica a cada sección:
| Sección | Clave de ejemplo | Variable generada |
|---|---|---|
colors | accent | --accent |
text | primary | --text-primary |
borders | radius | --border-radius |
layout | spacing | --spacing |
shadows | glow-accent | --glow-accent |
backgrounds | card | --bg-card |
backdrop | modal | --backdrop-blur-modal |
others | icon-filter | --icon-filter |
Notas importantes:
- El campo
[background]no se convierte en variables CSS. Se expone directamente como imagen de fondo del theme. - Las claves duplicadas generan una advertencia en los logs y se sobrescriben.
Ejemplo mínimo V2editar
Meta.toml:
[meta]
name = "Minimal"
author = "CubicLabs"
version = "1.0.0"Definition.toml:
[theme.background]
[theme.colors]
accent = "#ffffff"
bg-main = "#0a0a0a"
[theme.text]
primary = "#e5e5e5"Ejemplo completo V2editar
Meta.toml:
[meta]
name = "Midnight Blue"
author = "CubicLabs"
version = "2.0.0"
description = "Un tema oscuro con acentos azules."
injects_css = trueDefinition.toml:
[theme.background]
reference_path = "bg.webp"
image_blur = 8.0
image_opacity = 0.4
[theme.colors]
accent = "#3b82f6"
bg-main = "#0a0e17"
bg-card = "#111827"
[theme.text]
primary = "#e5e7eb"
secondary = "#9ca3af"
[theme.borders]
color = "#1f2937"
radius = "8px"
[theme.layout]
spacing = "1rem"
[theme.shadows]
glow-accent = "0 0 12px rgba(59, 130, 246, 0.3)"
[theme.backgrounds]
sidebar = "#0f172a"
[theme.backdrop]
modal = 8.0
dropdown = 4.0
[theme.others]
icon-filter = "invert(1)"
[[theme.fonts]]
family = "Inter"
src = "fonts/Inter.woff2"
format = "woff2"
weight = "400"
[[theme.fonts]]
family = "Inter"
src = "fonts/Inter-Bold.woff2"
format = "woff2"
weight = "700"
[theme.icons]
preview = "icons/preview.png"
[theme.icons.ui]
play = "icons/ui/play.svg"
settings = "icons/ui/settings.svg"
[theme.icons.sidebar]
home = "icons/sidebar/home.svg"Inject.css (opcional):
/* Personalizar las tarjetas del Market sin !important */
.market-item {
padding: 20px;
}Dimensiones y estilos de la interfazeditar
El cambio 5a7e752 amplía la personalización mediante variables CSS, sin cambiar el formato de los archivos. Los temas V1 pueden usar estas variables en variables; en V2 se declaran en las categorías de Definition.toml. Si omitís una variable, se conserva el valor predeterminado del launcher.
Listas y cuadrícula del Marketeditar
| Variable | Valor predeterminado | Uso |
|---|---|---|
--sidebar-width / --sidebar-compact-width | 260px / 70px | Ancho de la sidebar normal / compacta. |
--sidebar-row-height / --sidebar-compact-row-height | 52px / 50px | Altura de las filas de instancias en cada modo. |
--sidebar-row-gap | 8px | Separación de las filas de la sidebar. |
--version-row-height | 78px | Altura de fila en el selector de descargas de versiones. |
--resource-row-height / --resource-row-gap | 130px / 6px | Altura total de fila y separación en los catálogos de mods y paquetes de recursos. |
--resource-card-padding / --resource-icon-size | 14px 16px / 56px | Relleno de las tarjetas y tamaño de sus iconos. |
--market-row-height / --market-grid-gap | 224px / 12px | Altura total de fila y separación en el Market. |
--market-card-min-width | 280px | Ancho de referencia para calcular las columnas del Market (entre 1 y 4). |
--market-grid-padding | 8px | Espacio a la derecha de las filas del Market. |
--market-card-padding / --market-icon-size | 14px / 48px | Relleno de las tarjetas e iconos del Market. |
Las listas virtualizadas solo dibujan los elementos visibles. Usá estas variables para modificar sus medidas: cambiar únicamente height o los márgenes de una tarjeta con CSS puede desajustar el cálculo del desplazamiento. En el Market, la altura visible de la fila es --market-row-height menos --market-grid-gap; en recursos, la tarjeta descuenta --resource-row-gap de la altura total.
Las medidas se resuelven con CSS y se observan mediante ResizeObserver: admiten px, rem, calc() y var(), y se actualizan al cambiar el tamaño de fuente o cargarse Inject.css. Usá longitudes positivas para alturas y anchos; la separación y el padding de la cuadrícula del Market pueden ser 0px. Ajustá la altura total cuando aumentes el relleno, los iconos o el texto.
Colores, estados y efectoseditar
| Variables | Uso y valores predeterminados destacados |
|---|---|
--accent-text | Texto sobre botones de acento; #0a0a0a. Ajustalo junto con --accent para mantener el contraste. |
--surface-rgb, --surface-subtle, --surface-raised | Base RGB (255, 255, 255) y superficies con opacidad 0.02 / 0.04. En temas claros podés usar una base oscura. |
--border-hover, --border-focus | Bordes de interacción derivados de --surface-rgb con opacidad 0.1 / 0.3. |
--color-success, --color-error, --color-warning, --color-info | Colores semánticos: #22c55e, #ef4444, #eab308, #60a5fa. |
--color-on-success, --color-on-error, --color-on-warning, --color-on-info | Texto sobre fondos de estado; #fff. |
--color-status-starting, --color-status-started | Estado de inicio / ejecución; usan --color-info / --color-success. |
--toast-bg, --toast-border | Fondo y borde de notificaciones; derivados de --bg-card y --surface-rgb. |
--download-library, --download-asset, --download-native, --download-client | Colores de bibliotecas, assets, nativos y cliente: #4ade80, #60a5fa, #f59e0b, #a78bfa. |
--download-verifying, --download-generic, --download-processing, --download-jre | Verificación, descarga genérica, procesamiento y Java: #f472b6, #94a3b8, #fb923c, #22d3ee. |
--log-trace, --log-debug, --log-info, --log-message, --log-warn, --log-error, --log-fatal, --log-launcher, --log-stderr, --log-unknown | Colores por nivel/origen de log; por defecto derivan de los colores de texto y de estado. |
--media-overlay, --media-overlay-text, --viewer-overlay | Overlay sobre imágenes (rgba(0, 0, 0, 0.6)), texto (#fff) y visor (rgba(0, 0, 0, 0.9)). |
--shadow-inset, --shadow-floating, --shadow-image, --shadow-indicator | Sombras interiores, flotantes, de imágenes e indicadores. Las tres últimas usan --shadow-lg, --shadow-md y --shadow-sm. |
--shadow-drawer-left, --shadow-drawer-right, --shadow-drawer-top, --shadow-drawer-bottom | Sombras de paneles deslizantes según su dirección. |
--bg-image-brightness, --bg-image-size, --bg-image-position | Brillo (0.4), tamaño (cover) y posición (center) del fondo. El brillo es independiente de la opacidad y del desenfoque configurados en [theme.background]. |
Las variables --error y --warning se conservan como nombres legacy. Para temas nuevos preferí los colores semánticos --color-*. Si cambiás --accent, --color-success, --color-error o --color-warning, mantené sus variables *-rgb coherentes cuando se usen para transparencias; el valor RGB se escribe como "239, 68, 68", sin rgb().
Ejemplo V2: medidas y contrasteeditar
Este Definition.toml puede usarse con el Meta.toml mínimo anterior. Al adaptarlo a un tema existente, integrá las claves en sus secciones correspondientes: no repitas una misma tabla TOML.
[theme.background]
[theme.colors]
accent = "#d89b53"
accent-rgb = "216, 155, 83"
accent-hover = "#e5ad6d"
accent-text = "#17120d"
bg-main = "#17120d"
bg-sidebar = "#211a13"
bg-card = "#292017"
surface-rgb = "255, 240, 220"
log-warn = "#f1c875"
download-jre = "#8dcbb8"
[theme.text]
primary = "#f5eadb"
secondary = "#c6b6a1"
[theme.layout]
font-size-base = "14px"
sidebar-row-height = "4rem"
sidebar-compact-row-height = "4rem"
version-row-height = "6rem"
resource-row-height = "10rem"
resource-card-padding = "16px"
market-row-height = "calc(18rem + 12px)"
market-grid-gap = "12px"
market-card-min-width = "300px"
market-card-padding = "20px"
modal-width = "480px"
modal-padding = "24px"
icon-scale = "1.1"
[theme.others]
font-family-mono = "ui-monospace, Consolas, monospace"
bg-image-brightness = "0.55"Los valores de variables se escriben como strings, incluso los factores sin unidad como icon-scale. Usá [theme.layout] para generar --modal-width o --font-size-base, y [theme.others] para --font-family-mono. Poner font-family-mono en [theme.text] generaría --text-font-family-mono, que no controla la fuente monoespaciada.
Recursos adicionaleseditar
Imagen de fondoeditar
La imagen de fondo se configura de forma distinta según la versión:
- V1:
bg_image,bg_image_blur,bg_image_opacity. - V2: sección
[background]conreference_path,image_blur,image_opacity.
Formatos soportados: PNG, WEBP, JPG, JPEG y GIF (la validación interna utiliza infer, pero se recomienda PNG, WEBP o JPG para evitar problemas).
Si la imagen supera los 25 MB o no es reconocida como imagen válida, CubicLauncher la ignora y, en V1, registra una clave de advertencia.
Personalización de la sidebareditar
La sidebar de CubicLauncher se estiliza principalmente mediante variables CSS. Las siguientes variables controlan su apariencia:
| Variable | Descripción |
|---|---|
--bg-sidebar | Color sólido de fondo de la sidebar. |
--bg-sidebar-gradient | Gradiente aplicado sobre el fondo. Si está definido, tiene prioridad sobre --bg-sidebar. |
--sidebar-width | Ancho de la sidebar en modo normal. |
--bg-item-active | Fondo del item activo o seleccionado en la sidebar. |
--text-primary | Color del texto principal de la sidebar. |
--text-secondary | Color del texto secundario. |
--accent | Color de acento para botones y estados interactivos. |
--border-color | Color de bordes y separadores. |
Comportamiento del gradienteeditar
En el frontend la sidebar utiliza la siguiente regla:
background: var(--bg-sidebar-gradient, var(--bg-sidebar));Esto significa que si se define --bg-sidebar-gradient, se aplicará el gradiente. Si no está definido, se usará --bg-sidebar como color sólido de respaldo.
Modo normal y modo compactoeditar
La sidebar puede alternar entre dos modos desde la interfaz:
- Modo normal: utiliza el ancho definido por
--sidebar-width(valor por defecto:260px). - Modo compacto: conserva los mismos colores y gradientes, pero muestra solo iconos. Su ancho se controla con
--sidebar-compact-width(por defecto70px).
Ejemplo en V1editar
"variables": {
"--bg-sidebar": "#0f1010",
"--bg-sidebar-gradient": "linear-gradient(180deg, #1a1a2e 0%, #0f1010 100%)",
"--sidebar-width": "260px",
"--bg-item-active": "#1c1d1d",
"--text-primary": "#d8d8d8",
"--accent": "#3b82f6"
}Ejemplo en V2editar
[theme.colors]
bg-sidebar = "#0f1010"
bg-sidebar-gradient = "linear-gradient(180deg, #1a1a2e 0%, #0f1010 100%)"
bg-item-active = "#1c1d1d"
accent = "#3b82f6"
[theme.layout]
sidebar-width = "260px"
[theme.text]
primary = "#d8d8d8"En V2, las claves de la sección
colorsgeneran variables con el prefijo--directamente (bg-sidebar→--bg-sidebar), mientras que las claves delayouttambién generan variables con el prefijo--(sidebar-width→--sidebar-width).
Personalización de modaleseditar
Los modales de CubicLauncher usan una combinación de variables globales para definir el overlay, el desenfoque y el cuerpo del diálogo.
| Variable | Descripción |
|---|---|
--bg-overlay | Color o fondo del overlay oscuro que cubre la pantalla detrás del modal. |
--backdrop-blur-modal | Cantidad de desenfoque aplicado al overlay del modal. |
--bg-sidebar | Fondo del cuerpo del modal. CubicLauncher reutiliza este color para mantener consistencia visual. |
--border / --border-color | Color del borde del modal. |
--border-radius | Radio de borde del modal. |
--shadow-lg | Sombra proyectada del modal. |
--text-primary | Color del título y texto principal del modal. |
--text-muted | Color de botones secundarios y texto auxiliar. |
--modal-width | Ancho deseado; se limita a 90vw. Si se omite, usa el ancho del componente (400px si este no especifica otro). |
--modal-max-height | Altura máxima; por defecto 90vh. |
--modal-padding / --modal-gap | Relleno y separación del contenido; por defecto var(--space-xl) (24px) / 20px. |
--modal-title-size / --modal-footer-gap | Tamaño del título y separación de acciones; 1rem / 10px. |
--drawer-width / --drawer-max-height | Ancho de paneles laterales (340px, limitado a 90vw) y altura máxima de paneles superiores/inferiores (85vh). |
Comportamiento del overlayeditar
En el frontend, el overlay de un modal se define así:
background: var(--bg-overlay, rgba(0, 0, 0, 0.75));
backdrop-filter: blur(var(--backdrop-blur-modal, 4px));El CSS base ya define --bg-overlay como rgba(0, 0, 0, 0.7) y --backdrop-blur-modal como 4px. El valor 0.75 de esta regla solo es un respaldo si la variable no está disponible, no el valor base del launcher.
Nota sobre el fondo del modaleditar
El cuerpo del modal usa --bg-sidebar como color de fondo:
.modal {
background: var(--bg-sidebar);
}Esto significa que personalizando --bg-sidebar también se modifica la apariencia de los modales. Si querés un fondo diferente exclusivamente para modales, podés sobrescribirlo mediante Inject.css con un selector como .modal.
Ejemplo en V1editar
"variables": {
"--bg-overlay": "rgba(0, 0, 0, 0.85)",
"--backdrop-blur-modal": "6px",
"--bg-sidebar": "#141414",
"--border-color": "#2a2a2a",
"--border-radius": "12px",
"--shadow-lg": "0 8px 28px rgba(0, 0, 0, 0.6)",
"--text-primary": "#e5e5e5",
"--text-muted": "#888888"
}Ejemplo en V2editar
[theme.colors]
bg-overlay = "rgba(0, 0, 0, 0.85)"
bg-sidebar = "#141414"
[theme.borders]
color = "#2a2a2a"
radius = "12px"
[theme.backdrop]
modal = 6.0
[theme.shadows]
shadow-lg = "0 8px 28px rgba(0, 0, 0, 0.6)"
[theme.text]
primary = "#e5e5e5"
muted = "#888888"Personalización de scrollbarseditar
CubicLauncher estiliza las barras de desplazamiento mediante variables CSS que luego se aplican con selectores ::-webkit-scrollbar.
| Variable | Descripción |
|---|---|
--scrollbar-track | Fondo de la pista de la scrollbar. |
--scrollbar-thumb | Color del "pulgar" de la scrollbar. |
--scrollbar-thumb-hover | Color del pulgar al pasar el cursor. |
--scrollbar-size | Ancho y alto de las barras; por defecto 6px. |
--scrollbar-radius | Radio del pulgar; por defecto 10px. |
Comportamientoeditar
En el archivo base se usa:
::-webkit-scrollbar-track {
background: var(--scrollbar-track, transparent);
}
::-webkit-scrollbar-thumb {
background: var(--scrollbar-thumb, var(--border));
border-radius: var(--scrollbar-radius);
}
::-webkit-scrollbar-thumb:hover {
background: var(--scrollbar-thumb-hover, var(--text-secondary));
}El CSS base define la pista como var(--bg-main), el pulgar como rgba(var(--surface-rgb), 0.12) y el hover como var(--text-secondary). Los segundos argumentos de var() son respaldos si esas variables no están disponibles.
Nota sobre scrollbars internaseditar
Las barras internas de .qm-scroll y .modal también usan --scrollbar-size, --scrollbar-thumb y --scrollbar-radius. Algunos detalles siguen siendo locales, como la pista transparente de .qm-scroll; podés personalizarlos mediante Inject.css.
Ejemplo en V1editar
"variables": {
"--scrollbar-track": "#0c0c0c",
"--scrollbar-thumb": "#333333",
"--scrollbar-thumb-hover": "#555555"
}Ejemplo en V2editar
[theme.colors]
scrollbar-track = "#0c0c0c"
scrollbar-thumb = "#333333"
scrollbar-thumb-hover = "#555555"Personalización de tipografíaeditar
La tipografía base y los controles se personalizan con estas variables:
| Variable | Descripción |
|---|---|
--font-family | Fuente principal de toda la interfaz. |
--font-size-base | Tamaño de fuente base (14px); afecta a las medidas expresadas en rem. |
--font-family-mono | Fuente monoespaciada para logs y contenido técnico; por defecto una lista de fuentes del sistema. |
--font-size-sm / --font-size-lg | Tamaños pequeño / grande; 0.8rem / 1.2rem. |
--font-size-control / --font-size-label | Tamaño de controles / etiquetas; 0.85rem / 0.65rem. |
--font-weight-normal / --font-weight-medium / --font-weight-bold | Pesos de texto; 400 / 600 / 700. |
--line-height | Interlineado base; 1.5. |
--log-font-size / --log-line-height | Tamaño e interlineado de logs; 0.75rem / var(--line-height). |
--log-line-padding / --log-line-min-height | Relleno y altura mínima de líneas de log; 2px 14px / 22px. |
--control-padding / --button-padding | Relleno de controles / botones; 10px 12px / 8px 16px. |
--icon-scale | Factor de escala de los iconos que usan el componente común Icon; 1. |
--font-loaded | Flag interno que indica si la fuente personalizada ya cargó. Normalmente no es necesario modificarlo. |
Comportamientoeditar
En el CSS base se define:
html {
font-size: var(--font-size-base, 14px);
}
body {
font-family: var(--font-family);
}Esto significa que cambiar --font-size-base afecta proporcionalmente a todos los textos que usen unidades rem, y cambiar --font-family afecta toda la interfaz.
Usar una fuente personalizadaeditar
Para que --font-family funcione correctamente, se deben incluir los archivos de fuente en el theme y declararlos en la sección fonts. La familia declarada en fonts debe coincidir con el valor de --font-family.
Si la fuente tiene múltiples pesos o estilos, declará cada variante por separado.
Ejemplo en V1editar
{
"variables": {
"--font-family": "\"Inter\", system-ui, sans-serif",
"--font-size-base": "14px"
},
"fonts": [
{
"family": "Inter",
"src": "fonts/Inter-Regular.woff2",
"format": "woff2",
"weight": "400"
},
{
"family": "Inter",
"src": "fonts/Inter-Bold.woff2",
"format": "woff2",
"weight": "700"
}
]
}Ejemplo en V2editar
[meta]
name = "Tipografía personalizada"
author = "CubicLabs"
version = "1.0.0"Definition.toml:
[theme.background]
[theme.others]
font-family = "\"Inter\", system-ui, sans-serif"
[theme.layout]
font-size-base = "14px"
[[theme.fonts]]
family = "Inter"
src = "fonts/Inter-Regular.woff2"
format = "woff2"
weight = "400"
[[theme.fonts]]
family = "Inter"
src = "fonts/Inter-Bold.woff2"
format = "woff2"
weight = "700"En V2,
--font-familyy--font-size-baseno pertenecen a ninguna categoría semántica específica. Se recomienda definir--font-familyen[theme.others]y--font-size-baseen[theme.layout].
Fuentes personalizadaseditar
Tanto V1 como V2 permiten fuentes personalizadas mediante el siguiente schema:
[[theme.fonts]]
family = "Inter"
src = "fonts/Inter.woff2"
format = "woff2"
weight = "400"
style = "normal"| Campo | Descripción |
|---|---|
family | Nombre de la familia tipográfica. |
src | Ruta al archivo de fuente. Puede ser relativa al theme, absoluta o comenzar con file:. |
format | Formato de fuente (woff2, ttf, etc.). |
weight | Peso tipográfico (100 a 900, bold, etc.). |
style | Estilo (normal, italic, etc.). |
Iconos personalizados (solo V2)editar
V2 permite reemplazar iconos del frontend mediante la sección [theme.icons].
La estructura es la siguiente:
[theme.icons]
preview = "icons/preview.png"
[theme.icons.ui]
play = "icons/ui/play.svg"
settings = "icons/ui/settings.svg"| Campo | Descripción |
|---|---|
preview | Ruta al icono que se muestra como vista previa del theme en el listado. |
[icons.<grupo>] | Grupos de iconos. Cada clave dentro del grupo se expone al frontend como {grupo}:{nombre}. |
Ejemplo: la clave play dentro del grupo ui se expone como ui:play.
Restricciones:
- Extensiones permitidas:
svg,png,webp,jpg,jpeg. - Imágenes rasterizadas: máximo 2 MB.
- Se valida que el archivo sea una imagen válida (PNG/WEBP/JPG) o que exista (SVG).
Iconos inválidos se eliminan silenciosamente con una advertencia en los logs.
CSS inyectado (solo V2)editar
V2 permite incluir una hoja de estilos adicional llamada Inject.css en la raíz del theme.
Para indicar que el theme incluye CSS personalizado, establecé injects_css = true en Meta.toml:
[meta]
name = "Advanced Theme"
injects_css = trueEl contenido de Inject.css se lee y se envía al frontend en el campo inject_css del ThemeResponse, y el launcher lo aplica al activar el tema.
Desde 5a7e752, los estilos globales y los estilos encapsulados de Svelte se agrupan en @layer cubic. Las reglas normales de Inject.css fuera de cualquier capa tienen prioridad sobre las reglas normales de esa capa, sin necesitar las clases generadas de Svelte ni !important:
/* Inject.css: mantener estas reglas fuera de @layer cubic */
.market-item {
padding: 20px;
}
.modal {
background: var(--bg-card);
}
/* Medidas heredadas por la cuadrícula y sus observadores */
.market-grid {
--market-row-height: calc(18rem + 12px);
--market-grid-gap: 12px;
}La prioridad de capas no sustituye las reglas de los estilos inline ni de las declaraciones !important. Preferí definir variables globales en Definition.toml; si usás CSS, aplicalas al contenedor que las consume, como .market-grid. No sobrescribas los valores internos calculados (--row-height, --columns, alturas o transformaciones de las filas virtualizadas).
Al volver a un tema incluido, comprobá que desaparezcan las reglas inyectadas y se restauren las medidas predeterminadas.
Empaquetar un themeeditar
Un theme se distribuye como un archivo ZIP. Dentro del ZIP, los archivos deben estar dentro de una carpeta raíz con el nombre del theme.
Estructura del ZIP para V2editar
Autor_Tema.zip
└── NombreDelTheme/
├── Meta.toml
├── Definition.toml
├── Inject.css (opcional)
├── bg.webp (opcional)
├── fonts/
│ └── Inter.woff2
└── icons/
├── preview.png
└── ui/
├── play.svg
└── settings.svgEstructura del ZIP para V1editar
Autor_Tema.zip
└── NombreDelTheme/
├── theme.json
├── bg.webp (opcional)
└── fonts/
└── Inter.woff2Reglas del ZIPeditar
- El ZIP puede contener el archivo objetivo en la raíz (
theme.jsonoMeta.toml) o dentro de una subcarpeta. - Si existen múltiples archivos objetivo o múltiples subcarpetas con ellos, la importación se rechaza.
- El nombre del archivo ZIP para publicar en el repositorio oficial debe seguir el patrón
Autor_Tema.zip.
Probar un theme localmenteeditar
CubicLauncher expone varios comandos para importar themes. Durante el desarrollo, podés usar cualquiera de los siguientes métodos:
Importar un archivo JSON V1 directamenteeditar
Usá el comando import_theme y seleccioná el archivo theme.json.
Importar un ZIP V1 o V2editar
Usá el comando import_theme_zip. CubicLauncher intentará detectar automáticamente si es V1 (theme.json) o V2 (Meta.toml).
Importar un paquete V2 directamenteeditar
Usá el comando import_theme_cbth para archivos .cbth (formato de paquete V2).
Ubicación de themes instaladoseditar
El comando get_themes_dir_path devuelve la ruta donde CubicLauncher almacena los themes instalados. Durante el desarrollo, podés revisar esa carpeta para verificar que los archivos se extrajeron correctamente.
Comprobar las nuevas personalizacioneseditar
- Usá una compilación que incluya
5a7e752, importá el tema y activalo. - Revisá el contraste de botones con
--accent-text, notificaciones, logs, descargas y overlays. - Cambiá las alturas de sidebar, versiones y recursos, y las medidas
--market-*durante el desplazamiento. Comprobá que no aparezcan solapamientos ni huecos; repetí conremy otro--font-size-base. - En V2, probá
.market-item { padding: 20px; }enInject.csssin!importanty verificá que se aplique. Aumentá la altura de fila si el contenido necesita más espacio. - Revisá modales, iconos, fuentes monoespaciadas y brillo del fondo, también con desenfoque y animaciones desactivados desde el launcher.
- Volvé a un tema incluido y verificá que se restauren estilos y dimensiones; alterná entre dos temas para detectar valores residuales.
Publicar un themeeditar
¿Querés compartir tu tema con la comunidad? Enviá un Pull Request al repositorio oficial de Themes. Los temas publicados aparecen en la web oficial: cubiclauncher.org/themes.
Estructura del repositorioeditar
Cada tema vive bajo src/<Autor>/<Theme>/, con theme.md en la raíz del tema y una subcarpeta por versión (V1, V2, …):
V1/,V2/, … se refieren a versiones del tema dentro del repositorio, no al formato legacy V1 de CubicLauncher. Dentro de cada carpeta de versión se colocan los archivos del tema en el formato que prefieras (V2 recomendado).
src/
<Autor>/
<Theme>/
theme.md # descripción del tema (obligatorio)
vflag.txt # verificación del theme, solo staff (opcional)
V1/
Meta.toml # metadatos
Definition.toml # definiciones visuales
bg.png # imagen de fondo
fonts/ # fuentes personalizadas
Font.ttf
Showcase.png # vista previa (opcional)
changelog.md # cambios de la versión (opcional)
V2/ # nuevas versiones (opcional)
...Los archivos binarios (imágenes, fuentes) no se almacenan en Git. El workflow CI los sube automáticamente a Cloudflare R2 y luego los borra del repositorio. Por eso, en el repo solo persisten los archivos de texto: TOML, CSS, TXT, MD, etc.
Pasos para agregar tu temaeditar
- Creá
src/TuAutor/TuTema/theme.mdcon la descripción del tema. - Creá la carpeta de versión
src/TuAutor/TuTema/V1/. - Agregá
Meta.tomlyDefinition.toml(formato TOML de CubicLauncher). - Agregá
bg.png(o.jpg,.gif,.webp) como imagen de fondo. - (Opcional) Agregá
Showcase.pngcomo vista previa, fuentes enfonts/, eInject.css,icons/, etc. - (Opcional) Agregá
changelog.mdcon el registro de cambios de la versión. - Para publicar nuevas versiones del tema, creá
V2/,V3/, etc. - Abrí un Pull Request al repositorio.
Archivos del temaeditar
En la raíz del tema:
| Archivo | ¿Obligatorio? | Descripción |
|---|---|---|
theme.md | Sí | Descripción/README del tema en Markdown. |
vflag.txt | No | Flag de verificación del theme completo. Solo lo debe agregar el staff; si el autor lo incluye, el tema no será verificado. |
Dentro de cada carpeta de versión (V1/, V2/, …):
| Archivo | ¿Obligatorio? | Descripción |
|---|---|---|
Meta.toml | Sí | Metadatos del tema. |
Definition.toml | Sí | Definiciones visuales del tema. |
bg.EXT | Sí | Imagen de fondo. Formatos: PNG, GIF, WEBP, JPG. |
fonts/ | No | Fuentes personalizadas. |
Inject.css | No | CSS adicional (requiere injects_css = true en Meta.toml). |
icons/ | No | Iconos personalizados (solo formato V2). |
Showcase.png | No | Vista previa de esa versión (nombre case-insensitive). |
changelog.md | No | Cambios de esa versión. |
Ejemplo de theme.md:
# Mi Tema
Descripción en markdown del tema, su inspiración, etc.Ejemplo de changelog.md:
# V1
- Primer lanzamiento
- Tema oscuro con acentos verdesVerificación de themeseditar
El catálogo themes.json marca un theme con verified: true únicamente si existe un archivo llamado exactamente vflag.txt en src/<Autor>/<Theme>/, junto a theme.md. Puede estar vacío: su contenido no se lee.
Importante: el archivo
vflag.txtsolo lo debe agregar el staff. Si vos, como autor del theme, lo incluís en tu PR, tu tema no será verificado.
La verificación aplica al theme completo. Un directorio llamado vflag.txt o un archivo dentro de V1/, V2/, etc. no lo verifica. Sin el archivo, o al eliminarlo, el catálogo se genera con verified: false.
Agregar o quitar únicamente este flag actualiza el catálogo sin regenerar previews ni subir o eliminar assets en R2.
¿Cómo agregar solo un Showcase.png a un theme existente?editar
- Agregá
Showcase.pngasrc/<Autor>/<Theme>/V1/Showcase.png. - Hacé commit y push a
master(o abrí un PR).
El workflow sube el archivo a R2, actualiza showcaseUrl y preserva las URLs R2 existentes de los demás assets (bg, fuentes, etc.).
La preview se regenera automáticamente. Si
bg.pngno está en disco (ya fue subido a R2 en una ejecución anterior), la preview usará un gradiente como fallback.
¿Qué pasa después del merge?editar
El repositorio incluye un workflow Generate + Assets to R2 (.github/workflows/) que se ejecuta en push a master y en PR cuando se modifican archivos en src/:
- Detecta qué directorios de versión cambiaron (p. ej.
src/TuAutor/TuTema/V1). - Optimiza los PNGs nuevos con
oxipng. - Genera previews solo para los directorios modificados (
generate.js --dirs). - Mergea collections externas a
packages.json. - Sube a R2 los assets binarios nuevos, actualiza
themes.jsoncon URLs de R2, y borra los binarios locales (scripts/upload-assets.mjs). - Commitea y pushea los cambios (
[skip ci]para evitar loops).
El themes.json resultante se sirve estáticamente y es el que consume la web de CubicLauncher para mostrar y descargar los temas. No necesitás hacer nada extra: una vez aceptado tu PR, el tema aparece automáticamente en cubiclauncher.org/themes.
Archivo de temas — Themes Archiveeditar
También existe un workflow manual Themes Archive Release en la pestaña Actions. Al ejecutarlo genera un release GitHub llamado archive-YYYY-MM-DD-HHMM que contiene un ZIP con todos los temas y todas sus versiones:
- Reconstruye
src/completo descargando los archivos de texto desde GitHub raw y los assets binarios desde R2. - Adjunta
themes.json,packages.json,README.mdyLICENSE. - Verifica que el ZIP no supere los 2 GB límite de GitHub antes de publicarlo.
Assets en R2editar
- Los binarios se suben a
https://themes.cubiclauncher.org/con nombres hasheados (file.<hash8>.ext) yCache-Control: immutable. - Los archivos de texto se sirven desde GitHub raw.
- El bucket R2 tiene CORS habilitado para permitir descargas desde el frontend.
Ejemplo:
src/4xnl/Jadol/V1/bg.jpg
→ https://themes.cubiclauncher.org/src/4xnl/Jadol/V1/bg.132191b1.jpgLicencia del repositorioeditar
El repositorio de Themes está bajo CC0 1.0 Universal (dominio público). Al enviar tu tema, aceptás publicarlo bajo esa licencia. Recordá que las fuentes incluidas en tu tema mantienen su propia licencia: incluíla y usá solo fuentes que tengas derecho a redistribuir.
Diseñar themes con IA (agents.md)editar
Las IA pueden acelerar mucho el diseño de un theme, pero también tienden a reproducir combinaciones genéricas: fondos oscuros + acento azul, fuentes Inter y poco más. Para aprovecharlas sin caer en lo repetido, usá este prompt o adaptalo a tu asistente.
Este bloque funciona como una referencia tipo
agents.mdpara IA y creadores. Podés copiarlo, pegarlo en tu chat favorito y ajustarlo al concepto que quieras.
Prompt recomendado para agentes de IAeditar
Copiá y pegá esto en tu asistente, ajustando el concepto:
[ROL]
Sos un diseñador especializado en interfaces de escritorio para launchers de Minecraft. Vas a crear un theme para CubicLauncher en formato V2 (`Meta.toml` + `Definition.toml`).
[OBJETIVO]
Generar un theme visualmente único, con identidad clara y coherente, que NO sea un "tema oscuro con acentos azules genérico".
[REGLAS DE DISEÑO]
- Elegí una fuente de inspiración concreta y poco común: una estética de videojuego, una época del diseño, una subcultura visual, un movimiento artístico, etc.
- Evitá el acento por defecto azul/verde/morado. Proponé ocre, coral, turquesa apagada, lavanda grisácea, etc.
- Usá tipografías que aporten personalidad. Podés combinar una display para títulos y una sans legible para cuerpo.
- El fondo debe tener textura, patrón sutil o degradado atmosférico; no un color plano oscuro.
- Agregá iconos coherentes con el concepto.
- Usá `Inject.css` cuando variables solas no alcancen (sombras de neón, bordes con clip, filtros, etc.).
- Nombrá las variables de forma semántica y coherente.
[REGLAS TÉCNICAS]
- Formato V2.
- Consultar las variables reales de src/styles/shared/reset.css (referencia: commit 5a7e752); usar --accent-text y colores semánticos con contraste suficiente.
- Usar las variables de medidas para listas virtualizadas; no sobrescribir alturas ni transformaciones internas.
- Mantener las reglas de Inject.css fuera de @layer cubic para sobrescribir los estilos normales de los componentes sin !important.
- Rutas relativas para recursos.
- No incluir `vflag.txt`.
- Fondo ≤ 25 MB; iconos rasterizados ≤ 2 MB.
- Validar TOML antes de entregar.
[SALIDA ESPERADA]
1. `[meta]` con nombre, autor, versión, descripción e `injects_css` si aplica.
2. `[theme]` completo en `Definition.toml`.
3. Lista de archivos recomendados (bg, fuentes, iconos).
4. Breve explicación del concepto y por qué es único.Cómo evitar resultados genéricoseditar
- No pidas "un tema oscuro": pedí algo como "UI de terminal VT220", "aesthetic de vaporwave de mall", "diseño suizo brutalista", "interfaz de Pip-Boy", "estética lo-fi japonesa", etc.
- Limitá los colores "seguros": si la IA te da azul/verde/morado por defecto, pedile que cambie el acento a ocre, coral, turquesa apagada, lavanda grisácea, etc.
- Pedí imperfecciones deliberadas: ruido sutil en el fondo, bordes levemente desgastados, sombras largas, contrastes inusuales.
- Incorporá tipografía como identidad: una fuente con serifa para títulos en un launcher moderno puede ser más memorable que usar Inter en todos lados.
- Usá
Inject.csspara sellos visuales: bordes con gradiente, esquinas alternativas, efectos de cristal/neo, tipografía monoespaciada en ciertos paneles. - Revisá el
icons/: iconos custom son un diferenciador enorme; si no los dibujás manualmente, pedile a la IA un set coherente y exportalos en SVG.
Checklist antes de publicareditar
- El theme tiene un concepto claro, no solo "oscuro con acento".
- La paleta es distinguible de themes populares como Midnight Blue.
- Las fuentes cargan y la legibilidad es buena.
-
bg.pngtiene detalle, textura o degradado, no solo un color plano. - Los iconos (si los hay) son consistentes con el concepto.
- El TOML valida correctamente.
- No incluye
vflag.txt.
Referencia rápidaeditar
Tabla comparativa V1 vs V2editar
| Característica | V1 | V2 |
|---|---|---|
| Formato principal | JSON | TOML |
| Archivos del theme | theme.json | Meta.toml, Definition.toml |
| Recursos opcionales | Imagen de fondo, fuentes | Imagen de fondo, fuentes, iconos, CSS |
| Sistema de iconos | No | Sí |
| CSS inyectado | No | Sí (Inject.css) |
| Definición de variables | Plano y manual | Por categorías con prefijos automáticos |
| Sección de fondo | Campos en raíz | [background] en Definition.toml |
| Estado | Legacy | Recomendado |
Variables CSS comunes del frontendeditar
Estas variables no son obligatorias, pero se utilizan frecuentemente por el frontend y por la función extract_preview para generar la vista previa del theme:
| Variable | Uso típico |
|---|---|
--bg-main | Fondo principal. |
--bg-card | Fondo de tarjetas o paneles. |
--bg-sidebar | Fondo de la barra lateral. |
--accent | Color de acento. |
--text-primary | Color de texto principal. |
En V2, estas variables surgen de las secciones colors, backgrounds y text con los prefijos correspondientes.
Notas y buenas prácticaseditar
- Usá semver en el campo
versionpara mantener un historial claro de cambios. - Comprimí las imágenes: las imágenes de fondo tienen un límite de 25 MB y los iconos de 2 MB. Imágenes livianas mejoran el tiempo de carga.
- Preferí SVG o WEBP para iconos, ya que ofrecen mejor calidad y compresión.
- Validá el TOML/JSON antes de empaquetar. Errores de sintaxis hacen que CubicLauncher ignore silenciosamente el theme durante el listado.
- Mantené las rutas relativas dentro del ZIP para que el paquete sea portable.
- Documentá las licencias de las fuentes e imágenes que incluyas en tu
theme.md. - Evitá colisiones de variables en V2: si dos secciones generan la misma variable CSS, el tema emitirá una advertencia y un valor sobrescribirá al otro.
- Probá el theme localmente antes de publicarlo mediante
import_theme_zipo los comandos correspondientes.