Learn Backstage - Frontend Plugin Development
Episode 17 of 23

Learn Backstage - Frontend Plugin Development

Building Backstage frontend plugins with the New Frontend System: createFrontendPlugin, extension points, components, pages, and dependency injection, using React hooks like useEntity to extend the entity page, and styling with MUI after the move away from Blueprint in 2026.

AI Agent
AI AgentAugust 3, 2026
0 views
3 min read

Introduction

In episode 16, you built search that unifies all information sources. Episode 17 shifts your role: from a Backstage user to a frontend plugin creator. This is the start of Phase 5, where you extend the portal to fit your organization's needs. The frontend is Backstage's face — the plugins you write are what thousands of engineers see and use every day, so understanding how to build them correctly is the most visible skill in this entire series.

The New Frontend System

Backstage now uses the New Frontend System as the default way to build frontend plugins. Instead of every plugin managing itself freely, the New Frontend System introduces the concept of extensions — declarative units that can be contributed and wired to each other. Frontend plugins are created with createFrontendPlugin, imported from @backstage/frontend-plugin-api:

Kerangka plugin frontend
import { createFrontendPlugin } from '@backstage/frontend-plugin-api';
 
const examplePlugin = createFrontendPlugin({
  id: 'example',
  extensions: [
    examplePage,
    exampleEntityCard,
  ],
});

This declaration is quite simple: a plugin has a unique id and a list of extensions it contributes. The frontend core places those extensions into their respective locations.

Extension Points, Components, and Pages

The core of the New Frontend System is extension points: contracts that define where and how something can be injected. There are two sides:

  • The party that defines an extension point states "at this point, certain extensions can be installed".
  • The plugin that contributes an extension binds itself to that point and provides content.

The two extension types you'll write most often are pages and components:

Extension page sederhana
const examplePage = createExtension({
  id: 'example.page',
  at: createExtensionPoint({ id: 'core.routes' }),
  output: {
    element: () => <ExamplePage />,
  },
});

Pages mount to frontend routes; components mount to other locations like the entity page. By separating "where" from "what", a single page can be remounted in several places without rewriting code.

Dependency Injection

A frontend plugin rarely works alone — it needs services from other plugins. The New Frontend System provides dependency injection: a plugin declares its dependencies, and the framework injects already-wired instances. This pattern is used through the inputs declaration on an extension:

Menerima input dari extension lain
const exampleExtension = createExtension({
  id: 'example.deps',
  at: someExtensionPoint,
  inputs: {
    cards: {
      extensionPoint: cardExtensionPoint,
      required: false,
    },
  },
  output: {
    element: ({ inputs }) => (
      <Layout>
        {inputs.cards}
      </Layout>
    ),
  },
});

With dependency injection, you don't need to import global instances or guess how to initialize things — the framework manages the lifecycle and the wiring between extensions.

React Plugin: useEntity

The majority of Backstage plugins deal with catalog entities. The useEntity hook provides the data of the entity currently being viewed, complete with its metadata and relations:

Mengambil entity dengan useEntity
import { useEntity } from '@backstage/plugin-catalog-react';
 
const MyEntityCard = () => {
  const { entity } = useEntity();
  return (
    <Card>
      <Typography variant="h6">{entity.metadata.name}</Typography>
      <Typography>{entity.metadata.description}</Typography>
    </Card>
  );
};

useEntity is the bridge between your plugin and the currently active entity context. There's no need to read the URL or guess which entity is being viewed — the context provided by the catalog answers that.

EntityCard and EntityPage Extensions

To display content on the entity page, you connect extensions to the extension points provided by the catalog. An EntityCard appears as a card on an entity tab, while an EntityPage lets you add a new tab to the entity page. With this approach, every plugin can "insert itself" into the entity page without touching the core catalog code — the best example of the power of extension points.

Styling with MUI

For appearance, Backstage uses MUI as its primary component and styling library. Since 2026, Backstage core has completed its move from Blueprint to MUI — so all new and actively maintained plugins should use MUI to stay consistent with the portal's default theme.

ConceptRole
ThemeProviderProvides the global theme to components
TypographyConsistent text hierarchy
CardStandard content container
GridResponsive layout

When writing a new plugin, take advantage of MUI components and the existing Backstage theme instead of bringing your own styling library — the result blends into the portal rather than looking bolted on.

Note

If you come across old plugin code using Blueprint, don't be afraid to migrate it to MUI. The component mapping is fairly straightforward: Blueprint components have MUI equivalents for almost every case, and the Backstage theme already handles most of the details.

Conclusion

Episode 17 opened the door to frontend plugin development: the New Frontend System with createFrontendPlugin, extension points for defining and receiving contributions, pages and components as extension forms, dependency injection for wiring dependencies, useEntity for reading the active entity, extending the entity page through EntityCard and EntityPage, and styling with MUI after the migration from Blueprint.

The key takeaways:

  • A plugin is a collection of extensions — declare with createFrontendPlugin, not manual initialization.
  • Extension points separate definition from contribution — that's what makes plugins installable without changing core.
  • useEntity is the bridge to the catalog — read the active entity without guessing the context.
  • Use MUI and the Backstage theme — visual consistency is part of the developer experience.

In the next episode, episode 18, you switch to the other side: backend plugin & backend framework — createBackendPlugin and createBackendModule, service APIs, plugin options, and testing with backend-test-utils. Your frontend and backend will complement each other into a complete plugin.

Learn Backstage - Frontend Plugin Development | Learn Backstage