Theming, branding y la carta del menú

Objetivos del capítulo
  • Personalizar themes.json, logo y favicon.

  • Crear la página principal del portal (HomePage).

  • Soportar dark mode.

La carta del menú

Una IDP sin marca es como un restaurante con las paredes blancas y el menú plastificado. La marca importa: el developer abre el portal y debe reconocer que está "en casa". Backstage tematiza con un solo archivo: app-config.yaml apunta a un themes.json que define los colores primarios, el logo y el favicon.

El archivo themes.json

  "light": {
    "primaryColor": "#1976d2",
    "headerColor": "#0d47a1",
    "backgroundColor": "#ffffff",
    "fontColor": "#1a1a1a"
  },
  "dark": {
    "primaryColor": "#90caf9",
    "headerColor": "#0d47a1",
    "backgroundColor": "#121212",
    "fontColor": "#f5f5f5"
  },
Donde se aplica

El themes.json se monta en app-config.yaml con la clave app.branding. Los colores se aplican al header, al sidebar y al componente BackstageThemeProvider. Cualquier color nuevo debe validarse con WCAG AA.

Diagram
Figure 13. Capa de theme y override

Página principal del portal

La HomePage es lo primero que ve el developer al aterrizar. Por defecto, Backstage muestra un grid vacío; lo cambiamos:

import React from 'react';
import { HomePageToolkit } from '@backstage/plugin-home-react';

export const SazonHomePage = () => (
  📚 },
      { url: '/sazon-status', label: 'Service status', icon: 🟢 },
    ]}
  />
);
Compositor visual

Si quieres arrastrar y soltar widgets en la HomePage, instala @backstage/plugin-home (no home-react) y monta su HomePage con un compositor visual. HomePageToolkit es la versión programática.

Dark mode

Backstage detecta el modo del sistema operativo o del navegador. Para forzarlo o customizarlo:

app:
  branding:
    theme:
      mode: dark
      defaultTheme: dark
      lightTheme: my-light
      darkTheme: my-dark

Y en themes.json:

{
  "themes": [
    { "id": "my-light", "type": "light", "palette": { /* ... */ } },
    { "id": "my-dark",  "type": "dark",  "palette": { /* ... */ } }
  ]
}
Contraste en ambos modos

Si tus colores funcionan en light mode pero no en dark mode, el theme está mal diseñado. La regla: foreground y background deben tener contraste ≥ 4.5:1 en ambos modos.

Logo y favicon

  • app-config.yamlapp.branding.fullLogo (logo claro, fondo claro).

  • app-config.yamlapp.branding.iconLogo (icono en nav lateral).

  • app-config.yamlapp.branding.favicon (favicon del navegador).

app:
  branding:
    fullLogo: ./assets/logo-full.svg
    iconLogo: ./assets/logo-icon.svg
    favicon: ./assets/favicon.ico
Example 11. Receta del capítulo
  1. Crea themes.json con light y dark palettes.

  2. Móntalo en app-config.yaml con app.branding.theme.

  3. Personaliza logo y favicon en app.branding.

  4. Define una HomePage con <HomePageToolkit />.

  5. Verifica el contraste en ambos modos.

Resumen

  • themes.json define colores para light y dark.

  • app-config.yaml apunta al theme y a los logos.

  • Una HomePage propia se monta en App.tsx como ruta /.

  • El dark mode se detecta automáticamente o se fuerza con app.branding.theme.mode.

Glosario del capítulo

themes.json

Archivo que define paletas de colores light y dark.

branding

Sección de app-config.yaml con logos, favicon y theme.

HomePageToolkit

Componente de @backstage/plugin-home-react para construir HomePages programáticas.

WCAG AA

Nivel de accesibilidad que exige contraste 4.5:1 en texto.

Próximo capítulo

Scaffolder: de plantilla a producción —el plugin Scaffolder te permite generar proyectos a partir de plantillas.

Parte IV: Parte 4 — Scaffolder y Auth: el libro de recetas y la puerta

El Scaffolder, los templates, los actions y las forms. Después abrimos la puerta: GitHub OAuth, Keycloak/OIDC y RBAC. Profundizamos en el ecosistema de plugins, el threat model oficial, el Permission Framework y los golden paths completos de templates.