White-label y branding por organización
CÉNIT permite a cada cliente personalizar colores, logo y slug de
su organización. La detección de subdominio (<slug>.cenitams.com)
está implementada en modo pasivo: el middleware lo detecta y lo
expone via header, pero no enforce ni cambia comportamiento. El
white-label “completo” (dominio propio, login skin por slug, cookies
cross-subdomain) es fase 2 pendiente.
Para comercial
Sección titulada «Para comercial»- Problema que resuelve: el club no quiere que su staff vea la marca CÉNIT al abrir la app — quiere ver sus colores y logo.
- Casos típicos: Nacional ve azul/rojo Nacional y escudo del club. Otro cliente puede sobreescribir a sus colores con un par de hex values desde Settings.
- Planes que lo incluyen: marcada como
custom_branding(pro + enterprise enlib/plans.ts). Atención comercial: hoy la feature no está gateada en el código — un cliente esencial puede usarla sin pagar. Issue abierto. - Diferenciador vs competencia: la mayoría de las plataformas SaaS de performance vienen con su marca fija. Esto permite vender a clubes que tienen identidad visual fuerte.
Qué prometer hoy y qué NO prometer
Sección titulada «Qué prometer hoy y qué NO prometer»| Prometible hoy | NO prometer todavía |
|---|---|
| Colores primario y secundario | Dominio propio (app.miclub.com) |
| Logo en la barra lateral | Login con look del club antes de autenticarse |
Slug único (miclub.cenitams.com) | Cookies que sigan al usuario cross-subdomain |
Cómo lo usa el staff
Sección titulada «Cómo lo usa el staff»Acceso y permisos
Sección titulada «Acceso y permisos»Solo hop y dir pueden editar branding desde
/dashboard/settings.
Configuración
Sección titulada «Configuración»- Nombre de la org —
organizations.name. - Slug —
organizations.slug, kebab-case, único, 2–40 chars, validado en DB por CHECK (migration 085). - Logo —
organizations.logo_url, sube archivo a Supabase Storage. - Color primario —
organizations.primary_color(sobreescribe--azul). - Color secundario —
organizations.secondary_color(sobreescribe--rojo).
El Shell aplica los colores con <style dangerouslySetInnerHTML> inyectando las CSS custom properties al
HTML root. Ver Sistema de temas para el
listado completo de variables.
Detección de subdominio (fase 1 passive)
Sección titulada «Detección de subdominio (fase 1 passive)»middleware.ts corre detectOrgSubdomain(host) en cada request.
La lógica:
- Hosts ignorados (no son orgs):
cenitams.com,www.cenitams.com,cenitapp.com(legacy 302),localhost, IPs. - Cualquier otro host con >2 segmentos:
parts[0]es candidato a slug. - Si el slug matchea el regex kebab-case y mide 2–40 chars, se
propaga via header
x-org-subdomainal request.
Ningún consumer hoy lee ese header — queda disponible para fases
siguientes. Activando NEXT_PUBLIC_SUBDOMAIN_DEBUG=true se loggea
en cada request.
Cómo lo ve el jugador
Sección titulada «Cómo lo ve el jugador»Player surface: indirecto. El jugador ve los colores y logo de su club al abrir
/player, pero no accede via subdominio propio — usacenitams.comigual que el staff. Su sesión carga la org y aplica el branding.
Datos y métricas
Sección titulada «Datos y métricas»organizations.slug— único, kebab-case (migration 085 enforce formato).organizations.primary_color,secondary_color— hex strings.organizations.logo_url— URL a Supabase Storage.
Integraciones
Sección titulada «Integraciones»- Multi-tenant — el branding es por organización, igual que los datos.
- Sistema de temas — define qué CSS custom properties son sobreescribibles.
- Superadmin — al crear una org, el superadmin setea slug, colores y logo iniciales.
Limitaciones / roadmap
Sección titulada «Limitaciones / roadmap»Fase 1 — en producción
Sección titulada «Fase 1 — en producción»Slug + UI de branding + detección pasiva de subdominio. Todo
funciona pero ningún subdomain <slug>.cenitams.com está
configurado en Cloudflare DNS hoy.
Fase 2 — pendiente
Sección titulada «Fase 2 — pendiente»Para que miclub.cenitams.com realmente funcione:
- DNS wildcard
*.cenitams.comen Cloudflare. - Custom-domain config en Cloudflare Workers para que el host wildcard llegue al worker.
- Cookies cross-subdomain — Supabase auth cookies con
domain=.cenitams.compara que la sesión sobreviva entre subdominios. - Login skin por slug — en
/login, leerx-org-subdomainy renderizar logo/colores del club antes de que el usuario se autentique. - Enforcement — opcionalmente, redirigir a
cenitams.comsi el slug del subdominio no matchea la org del usuario logueado.
Fase 3 — dominio propio
Sección titulada «Fase 3 — dominio propio»app.miclub.com con CNAME a cenitams.com + Cloudflare custom
domain por cliente. Sin SPEC ni precio definido. Es candidato fuerte
a diferenciador Enterprise.
Gating comercial pendiente
Sección titulada «Gating comercial pendiente»custom_branding está en lib/plans.ts solo para pro/enterprise,
pero el formulario de Settings no chequea canUse. Un cliente
esencial hoy puede subir logo y cambiar colores sin pagar.