writing-custom-step-layouts--old.md

March 29, 2026 ยท View on GitHub

::::info This documentation is for Backstage apps that still use the old frontend system. If your app uses the new frontend system, read the current guide instead. ::::

Every form in each step rendered in the frontend uses the default form layout from react-jsonschema-form. It is possible to override this behaviour by supplying a ui:ObjectFieldTemplate property for a particular step:

parameters:
  - title: Fill in some steps
    ui:ObjectFieldTemplate: TwoColumn

This is the same field used by react-jsonschema-form but we need to add a couple of steps to ensure that the string value of TwoColumn above is resolved to a react component.

Registering a React component as a custom step layout

The createScaffolderLayout function is used to mark a component as a custom step layout:

import { scaffolderPlugin } from '@backstage/plugin-scaffolder';
import {
  createScaffolderLayout,
  LayoutTemplate,
} from '@backstage/plugin-scaffolder-react';
import { Grid } from '@material-ui/core';

const TwoColumn: LayoutTemplate = ({ properties, description, title }) => {
  const mid = Math.ceil(properties.length / 2);

  return (
    <>
      <h1>{title}</h1>
      <h2>In two column layout!!</h2>
      <Grid container justifyContent="flex-end">
        {properties.slice(0, mid).map(prop => (
          <Grid item xs={6} key={prop.content.key}>
            {prop.content}
          </Grid>
        ))}
        {properties.slice(mid).map(prop => (
          <Grid item xs={6} key={prop.content.key}>
            {prop.content}
          </Grid>
        ))}
      </Grid>
      {description}
    </>
  );
};

export const TwoColumnLayout = scaffolderPlugin.provide(
  createScaffolderLayout({
    name: 'TwoColumn',
    component: TwoColumn,
  }),
);

After you have registered your component as a custom layout then you need to provide the layouts to the ScaffolderPage:

import { MyCustomFieldExtension } from './scaffolder/MyCustomExtension';
import { TwoColumnLayout } from './components/scaffolder/customScaffolderLayouts';

const routes = (
  <FlatRoutes>
    ...
    <Route path="/create" element={<ScaffolderPage />}>
      <ScaffolderLayouts>
        <TwoColumnLayout />
      </ScaffolderLayouts>
    </Route>
    ...
  </FlatRoutes>
);

Using the custom step layout

Any component that has been passed to the ScaffolderPage as children of the ScaffolderLayouts component can be used as a ui:ObjectFieldTemplate in your template file:

parameters:
  - title: Fill in some steps
    ui:ObjectFieldTemplate: TwoColumn