Tu primer plugin frontend

Objetivos del capítulo
  • Crear un plugin frontend con createPlugin.

  • Definir una ruta y un RouteRef.

  • Integrar el plugin en app.tsx y montarlo con FlatRoutes.

  • Pintar una tabla con datos del backend.

El frontend, esa otra mitad

El :cap-02 mostró que Backstage son dos proyectos: la sala (frontend) y la cocina (backend). En el :cap-06 escribimos un plugin backend. Ahora le damos un panel al developer: una página React que muestre el estado de los servicios.

Construimos el plugin @sazon/plugin-sazon-status en el crate del capítulo.

createPlugin y RouteRef

El plugin frontend es un objeto declarativo. Define un id, opcionalmente unas rutas, y expone componentes que pueden ser montados en el shell.

import { createPlugin, createRouteRef, createRoutableExtension } from '@backstage/core-plugin-api';

export const rootRouteRef = createRouteRef({
  id: 'sazon-status',
});

export const sazonStatusPlugin = createPlugin({
  id: 'sazon-status',
  routes: {
    root: rootRouteRef,
  },
});
Qué hace cada pieza
  • :code:`createPlugin({ id })` — declara el plugin.

  • :code:`createRouteRef({ id })` — define un identificador de ruta reutilizable.

  • :code:`routes: { root: rootRouteRef }` — expone la ruta para que otros plugins la referencien.

FlatRoutes: el router del shell

El shell (packages/app/src/App.tsx) usa FlatRoutes para componer las páginas. Cada plugin expone un componente "routable" que el shell monta en una ruta:

export const SazonStatusPage = sazonStatusPlugin.provide(
  createRoutableExtension({
    name: 'SazonStatusPage',
    component: () =>
      import('./components/SazonStatusPage').then(m => m.SazonStatusPage),
    mountPoint: rootRouteRef,
  }),
);

En el App.tsx:

import { FlatRoutes } from '@backstage/core-app-api';
import { Route } from 'react-router-dom';
import { SazonStatusPage } from '@sazon/plugin-sazon-status';

<FlatRoutes>
  <Route path="/sazon-status" element={<SazonStatusPage />} />
</FlatRoutes>

El componente de página

Una página es un componente React que consume APIs y renderiza UI. Aquí una página con una tabla:

import React from 'react';
import {
  InfoCard,
  Table,
  TableColumn,
} from '@backstage/core-components';
import { useApi } from '@backstage/core-plugin-api';
import { catalogApiRef } from '@backstage/plugin-catalog-react';

type ServiceStatus = {
  service: string;
  status: 'healthy' | 'degraded' | 'down';
  checkedBy: string;
};

export const SazonStatusPage = () => {
  const catalogApi = useApi(catalogApiRef);

  // In real life, fetch from your /api/sazon-status backend.
  // Here we render a static table to keep the example minimal.
  const rows: ServiceStatus[] = [
    { service: 'sazon-web', status: 'healthy', checkedBy: 'pager-sazon' },
    { service: 'sazon-api', status: 'healthy', checkedBy: 'pager-sazon' },
    { service: 'sazon-worker', status: 'degraded', checkedBy: 'pager-sazon' },
  ];

  const columns: TableColumn[] = [
    { title: 'Service', field: 'service' },
    { title: 'Status', field: 'status' },
    { title: 'Checked by', field: 'checkedBy' },
  ];

  return (
    
      
  );
};
¿Por qué InfoCard y Table?

Son componentes de @backstage/core-components. Mantienen el look & feel consistente (theme, espaciado, tipografía) en todos los plugins. Si los usas, tu plugin se ve "de Backstage" sin esfuerzo.

Integrar el plugin en el shell

Para activar el plugin, edita packages/app/src/App.tsx:

  1. Importa el componente routable.

  2. Añade una <Route> apuntando a él.

  3. Opcionalmente, añade un enlace en SidebarItem para que aparezca en la nav lateral.

import { SidebarItem } from '@backstage/core-components';
import { useRouteRef } from '@backstage/core-plugin-api';
import ExtensionIcon from '@material-ui/icons/Extension';

<SidebarItem text="Sazón status" icon={ExtensionIcon} to="/sazon-status" />
Example 8. Receta del capítulo
  1. Crea plugins/sazon-status/ con package.json y dependencias de Backstage.

  2. Define createPlugin() + createRouteRef() en plugin.ts.

  3. Implementa SazonStatusPage como componente React.

  4. Registra el plugin en packages/app/src/App.tsx con FlatRoutes.

  5. Añade un SidebarItem para acceso rápido.

Resumen

  • Un plugin frontend = createPlugin() + rutas + componentes routable.

  • createRouteRef da un id reutilizable para la ruta.

  • FlatRoutes monta los componentes en el shell.

  • @backstage/core-components (InfoCard, Table, etc.) asegura consistencia visual.

Glosario del capítulo

createPlugin

Función de @backstage/core-plugin-api que declara un plugin frontend.

RouteRef

Identificador inmutable de una ruta, montado en el plugin.

FlatRoutes

Componente del shell que monta rutas planas (sin sub-routers).

InfoCard

Componente base con título y slot, de @backstage/core-components.

SidebarItem

Elemento de la nav lateral; se monta en Sidebar.

Próximo capítulo

Frontend: datos, APIs y APIs de Backstage —consumir el catalog, llamar a endpoints custom, manejar errores con NotificationApi.