Cargando

Cargando...

Cómo crear themes

De CubicLauncher Docs

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.

Referencia de compatibilidad

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ónFormatoEstadoRecomendación
V1JSON (theme.json)LegacySe mantiene por compatibilidad, pero no recibe nuevas funciones.
V2TOML (Meta.toml + Definition.toml)ActualSe 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, jpg o jpeg; 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.

Formato legacy no aceptado en el repositorio

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

plaintext
NombreDelTheme/
└── theme.json        # obligatorio

Recursos opcionaleseditar

  • bg.EXT — imagen de fondo.
  • Archivos de fuentes referenciados en fonts.

Schema de theme.jsoneditar

CampoTipoRequeridoDescripción
namestringSíNombre del theme.
authorstringNoAutor del theme.
versionstringNoVersión del theme (se recomienda semver).
typestringNoTipo del theme. Se expone tal cual en el listado.
variablesobjetoSíMapa de variables CSS clave: valor.
bg_imagestringNoRuta de la imagen de fondo.
bg_image_blurstringNoDesenfoque de la imagen de fondo. Se convierte a número si es posible.
bg_image_opacitynumberNoOpacidad de la imagen de fondo (0.0 a 1.0).
fontsarrayNoLista de fuentes personalizadas.

Fuentes en V1editar

Cada entrada del array fonts sigue este schema:

CampoTipoRequeridoDescripción
familystringSíNombre de la familia tipográfica.
srcstringSíRuta al archivo de la fuente.
formatstringNoFormato de la fuente, por ejemplo woff2.
weightstringNoPeso de la fuente, por ejemplo 400 o 700.
stylestringNoEstilo de la fuente, por ejemplo normal o italic.

Ejemplo completo V1editar

json
{
  "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_blur se recibe como string y 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

plaintext
NombreDelTheme/
├── Meta.toml           # metadatos
└── Definition.toml     # definiciones visuales

Recursos 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

CampoTipoRequeridoDescripción
namestringSíNombre del theme.
authorstringNoAutor del theme.
versionstringNoVersión del theme (se recomienda semver).
descriptionstringNoDescripción breve del theme.
injects_cssbooleanNoIndica si el theme incluye un archivo Inject.css.

Schema de Definition.tomleditar

CampoTipoDescripción
[background]secciónConfiguración de la imagen de fondo.
[background.reference_path]stringRuta de la imagen de fondo.
[background.image_blur]numberDesenfoque de la imagen.
[background.image_opacity]numberOpacidad de la imagen (0.0 a 1.0).
[colors]objetoColores del theme.
[text]objetoColores y estilos de texto.
[borders]objetoBordes y radios.
[layout]objetoEspaciados, anchos, alturas y demás valores de layout.
[shadows]objetoSombras y glows.
[backgrounds]objetoColores de fondo adicionales.
[backdrop]objetoValores de desenfoque de fondo (backdrop blur), en píxeles.
[fonts]arrayFuentes personalizadas.
[icons]secciónIconos personalizados.
[icons.preview]stringIcono de vista previa del theme.
[icons.<grupo>]objetoIconos agrupados por categoría.
[others]objetoVariables 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ónClave de ejemploVariable generada
colorsaccent--accent
textprimary--text-primary
bordersradius--border-radius
layoutspacing--spacing
shadowsglow-accent--glow-accent
backgroundscard--bg-card
backdropmodal--backdrop-blur-modal
othersicon-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:

toml
[meta]
name = "Minimal"
author = "CubicLabs"
version = "1.0.0"

Definition.toml:

toml
[theme.background]

[theme.colors]
accent = "#ffffff"
bg-main = "#0a0a0a"

[theme.text]
primary = "#e5e5e5"

Ejemplo completo V2editar

Meta.toml:

toml
[meta]
name = "Midnight Blue"
author = "CubicLabs"
version = "2.0.0"
description = "Un tema oscuro con acentos azules."
injects_css = true

Definition.toml:

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

css
/* 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

VariableValor predeterminadoUso
--sidebar-width / --sidebar-compact-width260px / 70pxAncho de la sidebar normal / compacta.
--sidebar-row-height / --sidebar-compact-row-height52px / 50pxAltura de las filas de instancias en cada modo.
--sidebar-row-gap8pxSeparación de las filas de la sidebar.
--version-row-height78pxAltura de fila en el selector de descargas de versiones.
--resource-row-height / --resource-row-gap130px / 6pxAltura total de fila y separación en los catálogos de mods y paquetes de recursos.
--resource-card-padding / --resource-icon-size14px 16px / 56pxRelleno de las tarjetas y tamaño de sus iconos.
--market-row-height / --market-grid-gap224px / 12pxAltura total de fila y separación en el Market.
--market-card-min-width280pxAncho de referencia para calcular las columnas del Market (entre 1 y 4).
--market-grid-padding8pxEspacio a la derecha de las filas del Market.
--market-card-padding / --market-icon-size14px / 48pxRelleno 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

VariablesUso y valores predeterminados destacados
--accent-textTexto sobre botones de acento; #0a0a0a. Ajustalo junto con --accent para mantener el contraste.
--surface-rgb, --surface-subtle, --surface-raisedBase RGB (255, 255, 255) y superficies con opacidad 0.02 / 0.04. En temas claros podés usar una base oscura.
--border-hover, --border-focusBordes de interacción derivados de --surface-rgb con opacidad 0.1 / 0.3.
--color-success, --color-error, --color-warning, --color-infoColores semánticos: #22c55e, #ef4444, #eab308, #60a5fa.
--color-on-success, --color-on-error, --color-on-warning, --color-on-infoTexto sobre fondos de estado; #fff.
--color-status-starting, --color-status-startedEstado de inicio / ejecución; usan --color-info / --color-success.
--toast-bg, --toast-borderFondo y borde de notificaciones; derivados de --bg-card y --surface-rgb.
--download-library, --download-asset, --download-native, --download-clientColores de bibliotecas, assets, nativos y cliente: #4ade80, #60a5fa, #f59e0b, #a78bfa.
--download-verifying, --download-generic, --download-processing, --download-jreVerificació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-unknownColores por nivel/origen de log; por defecto derivan de los colores de texto y de estado.
--media-overlay, --media-overlay-text, --viewer-overlayOverlay 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-indicatorSombras 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-bottomSombras de paneles deslizantes según su dirección.
--bg-image-brightness, --bg-image-size, --bg-image-positionBrillo (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.

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] con reference_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:

VariableDescripción
--bg-sidebarColor sólido de fondo de la sidebar.
--bg-sidebar-gradientGradiente aplicado sobre el fondo. Si está definido, tiene prioridad sobre --bg-sidebar.
--sidebar-widthAncho de la sidebar en modo normal.
--bg-item-activeFondo del item activo o seleccionado en la sidebar.
--text-primaryColor del texto principal de la sidebar.
--text-secondaryColor del texto secundario.
--accentColor de acento para botones y estados interactivos.
--border-colorColor de bordes y separadores.

Comportamiento del gradienteeditar

En el frontend la sidebar utiliza la siguiente regla:

css
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 defecto 70px).

Ejemplo en V1editar

json
"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

toml
[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 colors generan variables con el prefijo -- directamente (bg-sidebar → --bg-sidebar), mientras que las claves de layout tambié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.

VariableDescripción
--bg-overlayColor o fondo del overlay oscuro que cubre la pantalla detrás del modal.
--backdrop-blur-modalCantidad de desenfoque aplicado al overlay del modal.
--bg-sidebarFondo del cuerpo del modal. CubicLauncher reutiliza este color para mantener consistencia visual.
--border / --border-colorColor del borde del modal.
--border-radiusRadio de borde del modal.
--shadow-lgSombra proyectada del modal.
--text-primaryColor del título y texto principal del modal.
--text-mutedColor de botones secundarios y texto auxiliar.
--modal-widthAncho deseado; se limita a 90vw. Si se omite, usa el ancho del componente (400px si este no especifica otro).
--modal-max-heightAltura máxima; por defecto 90vh.
--modal-padding / --modal-gapRelleno y separación del contenido; por defecto var(--space-xl) (24px) / 20px.
--modal-title-size / --modal-footer-gapTamaño del título y separación de acciones; 1rem / 10px.
--drawer-width / --drawer-max-heightAncho 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í:

css
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:

css
.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

json
"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

toml
[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.

VariableDescripción
--scrollbar-trackFondo de la pista de la scrollbar.
--scrollbar-thumbColor del "pulgar" de la scrollbar.
--scrollbar-thumb-hoverColor del pulgar al pasar el cursor.
--scrollbar-sizeAncho y alto de las barras; por defecto 6px.
--scrollbar-radiusRadio del pulgar; por defecto 10px.

Comportamientoeditar

En el archivo base se usa:

css
::-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

json
"variables": {
  "--scrollbar-track": "#0c0c0c",
  "--scrollbar-thumb": "#333333",
  "--scrollbar-thumb-hover": "#555555"
}

Ejemplo en V2editar

toml
[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:

VariableDescripción
--font-familyFuente principal de toda la interfaz.
--font-size-baseTamaño de fuente base (14px); afecta a las medidas expresadas en rem.
--font-family-monoFuente monoespaciada para logs y contenido técnico; por defecto una lista de fuentes del sistema.
--font-size-sm / --font-size-lgTamaños pequeño / grande; 0.8rem / 1.2rem.
--font-size-control / --font-size-labelTamaño de controles / etiquetas; 0.85rem / 0.65rem.
--font-weight-normal / --font-weight-medium / --font-weight-boldPesos de texto; 400 / 600 / 700.
--line-heightInterlineado base; 1.5.
--log-font-size / --log-line-heightTamaño e interlineado de logs; 0.75rem / var(--line-height).
--log-line-padding / --log-line-min-heightRelleno y altura mínima de líneas de log; 2px 14px / 22px.
--control-padding / --button-paddingRelleno de controles / botones; 10px 12px / 8px 16px.
--icon-scaleFactor de escala de los iconos que usan el componente común Icon; 1.
--font-loadedFlag interno que indica si la fuente personalizada ya cargó. Normalmente no es necesario modificarlo.

Comportamientoeditar

En el CSS base se define:

css
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

json
{
  "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

toml
[meta]
name = "Tipografía personalizada"
author = "CubicLabs"
version = "1.0.0"

Definition.toml:

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-family y --font-size-base no pertenecen a ninguna categoría semántica específica. Se recomienda definir --font-family en [theme.others] y --font-size-base en [theme.layout].

Fuentes personalizadaseditar

Tanto V1 como V2 permiten fuentes personalizadas mediante el siguiente schema:

toml
[[theme.fonts]]
family = "Inter"
src = "fonts/Inter.woff2"
format = "woff2"
weight = "400"
style = "normal"
CampoDescripción
familyNombre de la familia tipográfica.
srcRuta al archivo de fuente. Puede ser relativa al theme, absoluta o comenzar con file:.
formatFormato de fuente (woff2, ttf, etc.).
weightPeso tipográfico (100 a 900, bold, etc.).
styleEstilo (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:

toml
[theme.icons]
preview = "icons/preview.png"

[theme.icons.ui]
play = "icons/ui/play.svg"
settings = "icons/ui/settings.svg"
CampoDescripción
previewRuta 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:

toml
[meta]
name = "Advanced Theme"
injects_css = true

El 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:

css
/* 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

plaintext
Autor_Tema.zip
└── NombreDelTheme/
    ├── Meta.toml
    ├── Definition.toml
    ├── Inject.css            (opcional)
    ├── bg.webp               (opcional)
    ├── fonts/
    │   └── Inter.woff2
    └── icons/
        ├── preview.png
        └── ui/
            ├── play.svg
            └── settings.svg

Estructura del ZIP para V1editar

plaintext
Autor_Tema.zip
└── NombreDelTheme/
    ├── theme.json
    ├── bg.webp               (opcional)
    └── fonts/
        └── Inter.woff2

Reglas del ZIPeditar

  • El ZIP puede contener el archivo objetivo en la raíz (theme.json o Meta.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

  1. Usá una compilación que incluya 5a7e752, importá el tema y activalo.
  2. Revisá el contraste de botones con --accent-text, notificaciones, logs, descargas y overlays.
  3. Cambiá las alturas de sidebar, versiones y recursos, y las medidas --market-* durante el desplazamiento. Comprobá que no aparezcan solapamientos ni huecos; repetí con rem y otro --font-size-base.
  4. En V2, probá .market-item { padding: 20px; } en Inject.css sin !important y verificá que se aplique. Aumentá la altura de fila si el contenido necesita más espacio.
  5. Revisá modales, iconos, fuentes monoespaciadas y brillo del fondo, también con desenfoque y animaciones desactivados desde el launcher.
  6. 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).

plaintext
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)
        ...
Archivos binarios

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

  1. Creá src/TuAutor/TuTema/theme.md con la descripción del tema.
  2. Creá la carpeta de versión src/TuAutor/TuTema/V1/.
  3. Agregá Meta.toml y Definition.toml (formato TOML de CubicLauncher).
  4. Agregá bg.png (o .jpg, .gif, .webp) como imagen de fondo.
  5. (Opcional) Agregá Showcase.png como vista previa, fuentes en fonts/, e Inject.css, icons/, etc.
  6. (Opcional) Agregá changelog.md con el registro de cambios de la versión.
  7. Para publicar nuevas versiones del tema, creá V2/, V3/, etc.
  8. Abrí un Pull Request al repositorio.

Archivos del temaeditar

En la raíz del tema:

Archivo¿Obligatorio?Descripción
theme.mdSíDescripción/README del tema en Markdown.
vflag.txtNoFlag 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.tomlSíMetadatos del tema.
Definition.tomlSíDefiniciones visuales del tema.
bg.EXTSíImagen de fondo. Formatos: PNG, GIF, WEBP, JPG.
fonts/NoFuentes personalizadas.
Inject.cssNoCSS adicional (requiere injects_css = true en Meta.toml).
icons/NoIconos personalizados (solo formato V2).
Showcase.pngNoVista previa de esa versión (nombre case-insensitive).
changelog.mdNoCambios de esa versión.

Ejemplo de theme.md:

markdown
# Mi Tema

Descripción en markdown del tema, su inspiración, etc.

Ejemplo de changelog.md:

markdown
# V1

- Primer lanzamiento
- Tema oscuro con acentos verdes

Verificació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.txt solo 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

  1. Agregá Showcase.png a src/<Autor>/<Theme>/V1/Showcase.png.
  2. 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.png no 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/:

  1. Detecta qué directorios de versión cambiaron (p. ej. src/TuAutor/TuTema/V1).
  2. Optimiza los PNGs nuevos con oxipng.
  3. Genera previews solo para los directorios modificados (generate.js --dirs).
  4. Mergea collections externas a packages.json.
  5. Sube a R2 los assets binarios nuevos, actualiza themes.json con URLs de R2, y borra los binarios locales (scripts/upload-assets.mjs).
  6. 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.md y LICENSE.
  • 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) y Cache-Control: immutable.
  • Los archivos de texto se sirven desde GitHub raw.
  • El bucket R2 tiene CORS habilitado para permitir descargas desde el frontend.
plaintext
Ejemplo:
  src/4xnl/Jadol/V1/bg.jpg
  → https://themes.cubiclauncher.org/src/4xnl/Jadol/V1/bg.132191b1.jpg

Licencia 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.md para 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:

text
[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.css para 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.png tiene 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ísticaV1V2
Formato principalJSONTOML
Archivos del themetheme.jsonMeta.toml, Definition.toml
Recursos opcionalesImagen de fondo, fuentesImagen de fondo, fuentes, iconos, CSS
Sistema de iconosNoSí
CSS inyectadoNoSí (Inject.css)
Definición de variablesPlano y manualPor categorías con prefijos automáticos
Sección de fondoCampos en raíz[background] en Definition.toml
EstadoLegacyRecomendado

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:

VariableUso típico
--bg-mainFondo principal.
--bg-cardFondo de tarjetas o paneles.
--bg-sidebarFondo de la barra lateral.
--accentColor de acento.
--text-primaryColor 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 version para 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_zip o los comandos correspondientes.
Categoría Guías