Certified Backstage Associate (CBA)
Templates
Template Basics
In this guide, you’ll learn how to create Backstage software templates using the standard Entity syntax. A template is defined like any other Entity, but its kind
is Template. At minimum, a template YAML must include metadata and three key sections under spec
: parameters, steps, and output.
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: python-template
title: Python Template
description: Template for creating a new Python application
spec:
owner: user:guest
type: service
parameters: [] # Form definition (see Parameters section)
steps: [] # Execution logic (see Steps section)
output: [] # Post-run outputs (see Output section)
Registering Your Template
After authoring your template YAML, register it in the Backstage catalog just like any other Entity. You can point Backstage at a URL, a local file, or let it scan repositories:
catalog:
locations:
- type: url
target: https://github.com/mygithub/my-template.yaml
- type: file
target: ../../examples/templates/my-template.yaml
Note
Backstage supports multiple location types (GitHub, S3, local). Configure caching and refresh intervals in your app-config for optimal performance.
1. Parameters: Building the Form
The parameters section defines the UI form pages and input fields to collect data from the user.
Form Pages
Each entry under parameters
represents a page or step in the multi-page form:
spec:
parameters:
- title: Fill in details
- title: Choose deployment
- title: Review & Create
Field Definitions
Within each page, declare properties for user inputs. These follow JSON Schema syntax:
spec:
parameters:
- title: Fill in details
properties:
username:
title: Name
type: string
description: The username to log in as
ui:
placeholder: my-username
autoFocus: true
password:
title: Password
type: string
description: Your super secret password
email:
title: Email
type: string
description: Your email address
ui:
widget: email
placeholder: [email protected]
age:
title: Age
type: number
description: Enter your age
minimum: 0
maximum: 120
relationshipStatus:
title: Relationship Status
type: string
enum:
- Single
- Married
- Divorced
gender:
title: Gender
type: string
enum:
- Male
- Female
- N/A
ui:
widget: radio
options:
inline: true
interests:
title: Select Interests
type: array
items:
type: string
enum:
- Hiking
- Movies
- Dancing
uniqueItems: true
ui:
widget: checkboxes
acceptTerms:
title: Accept Terms and Conditions
type: boolean
description: Please accept the terms and conditions
Note
Use JSON Schema validation (minimum
, maximum
, enum
) to enforce input constraints right in the form.
Conditional UI
Show or hide fields based on previous answers using dependencies
:
spec:
parameters:
- title: Deployment Options
properties:
deployApp:
title: Deploy application?
type: boolean
default: true
platform:
title: Deployment Platform
type: string
dependencies:
deployApp:
allOf:
- if:
properties:
deployApp:
const: true
then:
required: [platform]
Built-in Pickers
Backstage includes specialized UI widgets for common selections:
Picker | Purpose | Configuration snippet |
---|---|---|
EntityPicker | Select any catalog entity | ui.field: EntityPicker |
OwnerPicker | Choose a user or group | ui.field: OwnerPicker |
RepoUrlPicker | Pick or create a Git repo | ui.field: RepoUrlPicker |
spec:
parameters:
- title: Select References
properties:
componentEntity:
title: Component
type: string
ui:
field: EntityPicker
options:
allowArbitraryValues: false
owner:
title: Owner
type: string
ui:
field: OwnerPicker
options:
catalogFilter:
kind:
- User
- Group
repoUrl:
title: Repository Location
type: string
ui:
field: RepoUrlPicker
options:
allowedHosts:
- github.com
allowedOrganizations:
- my_organization
2. Steps: Executing Actions
Under steps, define the backend actions your template will perform. Steps consume parameter values and run tasks like fetching skeletons, publishing code, or registering the component.
spec:
steps:
- id: fetch-base
name: Fetch Base
action: fetch:template
input:
url: ./skeleton
values:
projectName: ${{ parameters.name }}
owner: ${{ parameters.owner }}
- id: publish
name: Publish to GitHub
action: publish:github
input:
allowedHosts: ['github.com']
description: "Service ${{ parameters.name }}"
repoUrl: ${{ parameters.repoUrl }}
- id: register
name: Register in Catalog
action: catalog:register
input:
repoContentsUrl: ${{ steps.publish.output.repoContentsUrl }}
catalogInfoPath: /catalog-info.yaml
Step ID | Action | Description |
---|---|---|
fetch-base | fetch:template | Download skeleton folder with injected values |
publish | publish:github | Push generated code to GitHub |
register | catalog:register | Add the new component to the Backstage catalog |
Templating Files
Files in your skeleton folder can use Handlebars-like syntax to inject values:
// skeleton/package.json
{
"name": "${{ values.projectName }}",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}
}
Backstage replaces ${{ values.projectName }}
with the user-provided parameters.name
.
Example catalog-info.yaml
in skeleton
:
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: ${{ values.projectName | dump }}
spec:
type: service
owner: ${{ values.owner }}
lifecycle: experimental
3. Output: Presenting Results
After a successful run, use the output section to display links or information back to the user:
spec:
output:
links:
- title: Repository
url: ${{ steps.publish.output.remoteUrl }}
- title: Open in catalog
icon: catalog
entityRef: ${{ steps.register.output.entityRef }}
Summary
Backstage templates are composed of three core sections:
- Parameters: Build a multi-page form with JSON Schema fields.
- Steps: Execute backend actions using the collected data.
- Output: Surface useful links and information after template execution.
Links and References
Watch Video
Watch video content