Readme logo

Backstage Readme Plugin

Created by AxisCommunications

Readme shows your repository README inside Backstage. It adds the doc to the Entity page so context is always one click away. You see purpose, how to run it, links, and any gotchas in the place where you work.

The plugin reads the README from the same folder as the catalog info file. It looks for common names and formats like md, rst, or txt. It can follow symlinks.It works with Backstage source control integrations such as GitHub, GitLab, and Gerrit. That makes it useful across many teams and hosting setups.

You get a small card on the overview that renders the README. You can open a full view when you need more space. It keeps the doc visible during everyday work. Onboarding is smoother. Incidents go faster when on call needs quick facts. Reviews move with less tab switching.Readme complements the docs you already keep in code. Teams that treat the README as the single source of truth will see the latest content in Backstage without extra steps. It fits well in self hosted setups and large catalogs.

The plugin is maintained in the Axis Communications plugin suite for Backstage. It is listed in the public Backstage plugin directory.

Installation Instructions

These instructions apply to self-hosted Backstage only.

Install the frontend package

Copy
yarn --cwd packages/app add @axis-backstage/plugin-readme

Add the Readme card to the entity page

Add the card to your entity page so users can see it.

Copy
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import Grid from '@material-ui/core/Grid';
import { EntityLayout, EntitySwitch } from '@backstage/plugin-catalog';
import { ReadmeCard } from '@axis-backstage/plugin-readme';

const overviewContent = (
  <>
    {/* other cards */}
    <Grid item md={6} xs={12}>
      <ReadmeCard />
    </Grid>
    {/* other cards */}
  </>
);

Render the card only when a README exists.

Copy
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import Grid from '@material-ui/core/Grid';
import { EntityLayout, EntitySwitch } from '@backstage/plugin-catalog';
import { ReadmeCard, isReadmeAvailable } from '@axis-backstage/plugin-readme';

const overviewContent = (
  <EntitySwitch>
    <EntitySwitch.Case if={isReadmeAvailable}>
      <Grid md={6} xs={12}>
        <ReadmeCard maxHeight={350} />
      </Grid>
    </EntitySwitch.Case>
  </EntitySwitch>
);

Optional full page route

Add a full height page inside the entity layout.

Copy
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import { EntityLayout } from '@backstage/plugin-catalog';
import { ReadmeCard } from '@axis-backstage/plugin-readme';

const entityPage = (
  <EntityLayout>
    {/* other routes */}
    <EntityLayout.Route path="/readme" title="README">
      <ReadmeCard variant="fullHeight" />
    </EntityLayout.Route>
  </EntityLayout>
);

Install the backend package for the legacy backend

Copy
yarn --cwd packages/backend add @axis-backstage/plugin-readme-backend

Wire the router in the legacy backend

Create a small plugin file that builds the router.

Copy
// packages/backend/src/plugins/readme.ts
import { createRouter } from '@axis-backstage/plugin-readme-backend';
import { PluginEnvironment } from '../types';
import { CatalogClient } from '@backstage/catalog-client';

export default async function createPlugin(env: PluginEnvironment) {
  const catalogClient = new CatalogClient({ discoveryApi: env.discovery });

  return await createRouter({
    logger: env.logger,
    reader: env.reader,
    discovery: env.discovery,
    tokenManager: env.tokenManager,
    config: env.config,
    catalogClient,
  });
}

Mount the router under the readme path.

Copy
// packages/backend/src/index.ts
import readme from './plugins/readme';

// inside main function where apiRouter is created
const readmeRouter = await readme(env);
apiRouter.use('/readme', readmeRouter);

The frontend will call the backend at api readme. Backstage will proxy to this path.

Install the backend package for the new backend system

Copy
yarn --cwd packages/backend add @axis-backstage/plugin-readme-backend

Register the module in the new backend system

Add the module from the backend package to your backend builder. The export name can be readmeModule or readmePlugin depending on the version. Import the module from the same package then add it to the backend instance.

Copy
// packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';
import { readmeModule } from '@axis-backstage/plugin-readme-backend';
// If your version exports readmePlugin instead, import that and use it the same way
// import { readmePlugin } from '@axis-backstage/plugin-readme-backend';

const backend = createBackend();

// Use the export available in your version
backend.add(readmeModule());
// or
// backend.add(readmePlugin());

backend.start();

This registers the readme plugin at the readme path under api. The frontend will find it through discovery.

How the plugin finds the README

The plugin reads the README file from the same directory as the catalog info file. It supports md MD rst and txt file types. Symlinks are supported.

Troubleshooting

No README file found at the source location

Make sure the README file is in the same directory as the catalog info file in the repo. Then refresh the entity in the catalog.

Also check the backstage source location annotation. It must end with a trailing slash.

Copy
metadata:
  annotations:
    # This will not work
    backstage:source-location: https://bitbucket.org/org-name/repo-id/src/master
    # This will work
    backstage:source-location: https://bitbucket.org/org-name/repo-id/src/master/

Changelog

This changelog is produced from commits made to the Readme plugin since a year ago, and based on the code located here. It may not contain information about all commits. Releases and version bumps are intentionally omitted. This changelog is generated by AI.

Features

  • Add maxHeight prop to ReadmeCard for custom height control #195 merged 12 months ago
  • Hide ReadmeCard when backend returns 404 using the exported isReadmeAvailable helper #194 merged 12 months ago
  • Improve full view in ReadmeCard #298 merged 1 month ago
    • Use MUI FullscreenIcon for the full view dialog
    • Keep full view state in the URL so you can link to it

Dependencies

  • Bump Backstage to 1.42 to keep the plugin current with the new frontend system #319 merged 1 month ago
  • Bump Backstage to 1.40 plus other dependency updates #295 merged 2 months ago
  • Fix missing peer dependencies and update packages #267 merged 6 months ago
  • Bump Backstage to 1.36.1 to restore compatibility for consumers #259 merged 7 months ago

Set up Backstage in minutes with Roadie