Personalización de Assets
Flexygo Core permite personalizar la apariencia visual del producto en todos los niveles sin modificar el núcleo de la plataforma. Las personalizaciones se realizan mediante archivos de assets — CSS, JS, favicon, manifiesto PWA y variables de tema — que sobreviven a las actualizaciones de la aplicación.
Niveles de personalización y prioridad
Flexygo resuelve los assets mediante una cadena de 3 niveles. Cada nivel puede proporcionar su propia versión de cualquier archivo soportado. Los niveles superiores tienen prioridad.
| Prioridad | Nivel | Raíz de ruta | Quién lo usa |
|---|---|---|---|
| 1 (mayor) | Instalación | custom/ |
Instalaciones de cliente final |
| 2 | Producto | {carpeta-producto}/ |
Branding del producto / white-label |
| 3 (menor) | Flexygo | (raíz de wwwroot) | Valores nativos de Flexygo |
Cómo funciona la prioridad:
- Para archivos CSS/JS, se emiten en la página todos los niveles que contengan el archivo, en orden de menor a mayor prioridad. La cascada CSS del navegador y el orden de ejecución de scripts permiten que las personalizaciones de mayor prioridad ganen.
- Para archivos únicos (
manifest.json,favicon.ico), solo se usa el archivo encontrado con mayor prioridad (first-found-wins).
Descubrimiento automático de la carpeta de producto
La carpeta de producto se descubre automáticamente al iniciar la aplicación — no necesitas configurar su nombre. El sistema explora los subdirectorios de wwwroot en busca de uno que contenga la misma estructura de directorios que un asset nativo de Flexygo. La primera coincidencia gana.
Convención: carpeta creada por el instalador
El instalador de Flexygo Core ya crea automáticamente la carpeta de producto durante la creación o migración de un proyecto. Esta es la carpeta que debes usar como convención para todas tus personalizaciones a nivel de producto. No es necesario que crees una manualmente ni que adivines el nombre — utiliza la que el instalador ha generado.
Nombres de carpeta válidos
El nombre de la carpeta de producto solo puede contener caracteres [a-zA-Z0-9_-]+. Otros caracteres serán rechazados por seguridad.
Estructura de directorios esperada
Nivel Producto ({carpeta-producto}/)
wwwroot/
mi-producto/ ← Tu carpeta de producto (cualquier nombre válido)
manifest.json ← Manifiesto PWA
favicon.ico ← Favicon del producto
css/
theme.less ← Variables de tema del producto
views/
account/
account.css ← CSS genérico de cuenta
login/login.css ← CSS específico de página
register/register.css
forgot/forgot.css
authentication/authentication.css
manage-password/manage-password.css
js/
views/
account/
account.js ← JS genérico de cuenta
login/login.js ← JS específico de página
register/register.js
forgot/forgot.js
authentication/authentication.js
manage-password/manage-password.js
Nivel Instalación (custom/)
wwwroot/
custom/
manifest.json ← Sobrescritura de manifiesto PWA
favicon.ico ← Sobrescritura de favicon
css/
theme.less ← Variables de tema de instalación
views/
account/
account.css ← CSS genérico de cuenta
login/login.css
register/register.css
...
js/
views/
account/
account.js ← JS genérico de cuenta
login/login.js
register/register.js
...
Nota de compatibilidad: Existe una ruta plana heredada
custom/css/account.csspara la vista de Mantenimiento. El sistemaAssetOverrideResolverusa la estructura anidadacustom/css/views/account/documentada aquí. Planifica una migración futura si actualmente dependes de la ruta plana.
Assets Soportados
manifest.json — Manifiesto PWA
Resolución: First-found-wins (solo se usa el archivo de mayor prioridad).
| Nivel | Ruta |
|---|---|
| Instalación | custom/manifest.json |
| Producto | {producto}/manifest.json |
| Flexygo | manifest.json |
Ejemplo — Manifiesto a nivel de producto:
{
"name": "MiProducto",
"short_name": "MiProducto",
"start_url": "/",
"display": "standalone",
"icons": [{
"src": "assets/icon/icon192.png",
"sizes": "192x192",
"type": "image/png"
}, {
"src": "assets/icon/icon512.png",
"sizes": "512x512",
"type": "image/png"
}],
"background_color": "#1a1a2e",
"theme_color": "#e94560"
}
Coloca este archivo en wwwroot/{producto}/manifest.json.
theme.less — Variables de Tema y Propiedades CSS
Propósito: Recibir valores específicos del producto desde la base de datos, asignarlos a variables Less y exponerlos como propiedades CSS personalizadas (--*).
Resolución: Se concatenan los 3 niveles (Flexygo → Producto → Instalación). El pipeline ReplaceLessVars procesa el theme.less de cada nivel: los placeholders dbColor()/dbSize() se reemplazan con valores calculados desde base de datos, y las variables Less se convierten en propiedades CSS mediante :root { --*: @variable; }.
| Nivel | Ruta |
|---|---|
| Instalación | custom/css/theme.less |
| Producto | {producto}/css/theme.less |
| Flexygo | css/theme.less |
Estructura de un archivo theme.less:
/* === PASO 1: Mapear valores de base de datos a variables Less === */
@header-color: dbColor(HeaderColor);
@menu-color: dbColor(MenuColor);
@bg-color: dbColor(bgColor);
@primary-color: dbColor(PrimaryColor);
@danger-color: dbColor(DangerColor);
@small: dbSize(small);
@large: dbSize(large);
/* ... variables adicionales ... */
/* === PASO 2: Exponer como propiedades CSS personalizadas === */
:root {
color-scheme: light dark;
&:has(body[mode="light"]) { color-scheme: light; }
&:has(body[mode="dark"]) { color-scheme: dark; }
--header-color: @header-color;
--menu-color: @menu-color;
--bg-color: @bg-color;
--primary-color: @primary-color;
--danger-color: @danger-color;
}
Ejemplo a nivel de producto — añade tus propios colores de marca:
/* mi-producto/css/theme.less */
/* Añadir variables Less mapeadas a BD */
@brand-accent: dbColor(BrandAccent);
@brand-bg: dbColor(BrandBg);
@brand-text: dbColor(BrandText);
/* Exponer propiedades CSS de marca */
:root {
--brand-accent: @brand-accent;
--brand-bg: @brand-bg;
--brand-text: @brand-text;
--brand-radius: 12px;
--brand-shadow: 0 4px 24px rgba(0, 0, 0, 0.3);
}
Solo dos bloques permitidos
theme.less solo admite dos tipos de bloques: (1) definiciones @variable: dbColor()/dbSize(), y (2) el bloque :root { --*: @variable; }. No añadas mixins, reglas CSS ni otras construcciones — pertenecen a archivos .less separados.
Nuevas variables en base de datos
dbColor(Nombre) y dbSize(Nombre) se reemplazan en tiempo de ejecución con valores de la base de datos de configuración. Si introduces nuevas claves, regístralas en la tabla Skins_Variables desde el apartado Skins de la aplicación o directamente en la base de datos. Recuerda incluir estas variables en los scripts del proyecto ({Nombre}.Conf.Database) para que no se pierdan en otros entornos.
favicon.ico — Icono de Pestaña del Navegador
Resolución: First-found-wins.
| Nivel | Ruta |
|---|---|
| Instalación | custom/favicon.ico |
| Producto | {producto}/favicon.ico |
| Flexygo | favicon.ico |
Coloca un archivo .ico en el nivel deseado. Se recomiendan los tamaños estándar (16×16, 32×32, 48×48).
account.css — Estilos Genéricos de Páginas de Cuenta
Resolución: Los 3 niveles se emiten como etiquetas <link> en orden: Flexygo → Producto → Instalación. La cascada del navegador permite que las reglas posteriores sobrescriban a las anteriores.
| Nivel | Ruta |
|---|---|
| Instalación | custom/css/views/account/account.css |
| Producto | {producto}/css/views/account/account.css |
| Flexygo | css/views/account/account.css |
Ejemplo de branding a nivel de producto:
/* mi-producto/css/views/account/account.css */
/* Reemplazar el logo del producto */
:root {
--product-logo: url(mi-producto-logo.svg);
--product-background: url(mi-producto-background.svg);
}
/* Estilizar la tarjeta de cuenta */
.account-card {
border-radius: 16px;
box-shadow: 0 8px 32px rgba(233, 69, 96, 0.15);
}
/* Estilizar el botón de login */
.account-card .account-button {
background-color: var(--brand-accent, #e94560);
color: #fff;
font-weight: 600;
border-radius: 8px;
transition: background-color 0.2s ease;
}
.account-card .account-button:hover {
background-color: color-mix(in srgb, var(--brand-accent, #e94560) 80%, black);
}
/* Anillo de foco en los inputs */
.account-card-body .cell:focus-within {
outline-color: var(--brand-accent, #e94560);
}
/* Fondo de la página */
body {
background-color: #0f0f1a;
background-image: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
}
Variables CSS disponibles (definidas en el account.css de Flexygo):
| Propiedad | Propósito |
|---|---|
--product-logo |
Imagen del logo en la cabecera del icono |
--product-background |
Imagen de fondo tras la tarjeta de login |
--card-color |
Fondo de la tarjeta de cuenta |
--border-card-color |
Color del borde de la tarjeta |
--bg-color |
Color de fondo de la página |
--bg-color-light |
Fondo de los campos de entrada |
--bg-color-dark |
Fondo de los botones |
--bg-color-dark-2 |
Fondo hover de los botones |
--txt-color |
Color del texto |
--primary-color |
Anillo de foco, barra de carga, acentos |
--danger-color |
Color de error de validación |
--outstanding-color |
Scrollbar, destacados |
--success-color |
Indicadores de éxito |
--account-card-height |
Altura de la tarjeta (defecto: 600px) |
--account-card-width |
Anchura de la tarjeta (defecto: 440px) |
--input-height |
Altura de inputs/botones (defecto: 50px) |
--input-margin |
Padding horizontal en inputs |
--font-size-1 |
Texto grande (3em) |
--font-size-2 |
Texto normal (1em) |
--font-size-3 |
Texto pequeño (0.9em) |
--placeholder-color |
Texto del placeholder |
--outline-size |
Grosor del anillo de foco |
--login-font |
Familia tipográfica para páginas de cuenta |
account.js — Scripts Genéricos de Páginas de Cuenta
Resolución: Igual que account.css — los 3 niveles se emiten en orden de fuente.
| Nivel | Ruta |
|---|---|
| Instalación | custom/js/views/account/account.js |
| Producto | {producto}/js/views/account/account.js |
| Flexygo | js/views/account/account.js |
Scripts idempotentes
Los scripts de sobrescritura deben ser idempotentes: se ejecutan junto al script nativo, no en su lugar. Usa event listeners en vez de reemplazar funciones globales.
CSS y JS Específicos por Página
Cada página de Cuenta admite sus propias sobrescrituras de CSS y JS. El patrón es idéntico al de account.css/account.js.
| Página | Ruta CSS | Ruta JS |
|---|---|---|
| Login | css/views/account/login/login.css |
js/views/account/login/login.js |
| Registro | css/views/account/register/register.css |
js/views/account/register/register.js |
| Olvidé mi contraseña | css/views/account/forgot/forgot.css |
js/views/account/forgot/forgot.js |
| MFA | css/views/account/authentication/authentication.css |
js/views/account/authentication/authentication.js |
| Gestionar contraseña | css/views/account/manage-password/manage-password.css |
js/views/account/manage-password/manage-password.js |
Todas siguen la misma estructura {nivel}/{ruta}. Ejemplo para CSS de login a nivel de producto:
wwwroot/mi-producto/css/views/account/login/login.css
Referencia Rápida: Todas las Rutas Soportadas
{nivel}/manifest.json
{nivel}/favicon.ico
{nivel}/css/theme.less
{nivel}/css/views/account/account.css
{nivel}/css/views/account/login/login.css
{nivel}/css/views/account/register/register.css
{nivel}/css/views/account/forgot/forgot.css
{nivel}/css/views/account/authentication/authentication.css
{nivel}/css/views/account/manage-password/manage-password.css
{nivel}/js/views/account/account.js
{nivel}/js/views/account/login/login.js
{nivel}/js/views/account/register/register.js
{nivel}/js/views/account/forgot/forgot.js
{nivel}/js/views/account/authentication/authentication.js
{nivel}/js/views/account/manage-password/manage-password.js
Donde {nivel} es:
- Instalación:
custom(ej.custom/favicon.ico,custom/css/views/account/account.css) - Producto: el nombre de tu carpeta de producto (ej.
mi-producto/favicon.ico,mi-producto/css/views/account/account.css) - Flexygo: vacío / raíz (ej.
favicon.ico,css/views/account/account.css)
Limitaciones y Comportamiento de Degradación
- Detección de carpeta de producto se ejecuta una sola vez al inicio. Si no se encuentra ninguna carpeta de producto, el sistema se degrada a una cadena de 2 niveles (Instalación → Flexygo).
- Múltiples carpetas de producto generan una advertencia en el log; solo se usa la primera carpeta encontrada.
- Archivos ausentes en cualquier nivel se omiten silenciosamente — solo se emiten los archivos que existen.
manifest.jsonyfavicon.icousan el patrón first-found-wins; el fallback nativo de Flexygo siempre está disponible.- Sobrescritura de vistas (archivos
.cshtml) no está soportada en la versión actual. Las sobrescrituras de CSS/JS cubren la mayoría de necesidades de personalización. - Hot reload de archivos de personalización no está soportado; se requiere un reinicio de la aplicación tras desplegar nuevos assets.