How to Build Golden Paths in Backstage IDP with Software Templates
Stop letting developers reinvent the wheel. Standardize service creation with Backstage Software Templates and the Scaffolder.
Building New Services Doesn’t Have to Be Painful
In the previous parts of this series, we built a beautiful catalog filled with existing services and their documentation.
But what happens when a developer needs to create something new?
Most of the time, they copy-paste the last service they worked on, delete the old code, and cross their fingers that the configuration doesn’t break.
The result? Drift.
- Outdated CI/CD pipelines
- Inconsistent security scans
- Messy folder structures
Sound familiar? That’s the exact problem Platform Engineering aims to solve.
Enter the Golden Path
A Golden Path is like a paved road for developers. Stay on it, and security, compliance, and deployment are handled automatically. No guesswork. No accidental detours.
In Backstage, we build Golden Paths using Software Templates powered by the internal Scaffolder engine.
Today, we’ll break down:
- The anatomy of a Software Template
- How to collect user input efficiently
- How to execute automated steps to bootstrap a new repository
Think of it as laying down the road so developers can focus on building, not patching.
Let’s get started — it’s time to pave the way.
The Anatomy of a Software Template
In Backstage, a Software Template is defined by a single YAML file — usually named template.yaml
Think of it as a recipe for creating new services. This file does three critical things:
- Metadata: What is this template called, and who owns it?
- Input Parameters (
parameters): What questions do we need to ask the developer hitting the “Create” button? - Execution Steps (
steps): What automated actions should Backstage take once the developer submits their input? - Output (
output): What should the template return or link to once the service is created?
Here’s the high-level skeleton of a template.yaml:
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: spring-boot-microservice
title: Spring Boot Microservice
description: Create a standard Spring Boot Java service pre-configured with our CI/CD.
spec:
owner: platform-team
type: service
# 1. Ask the User for Input
parameters:
- {}
# 2. Execute Automated Steps
steps:
- {}
# 3. Output the Result
output:
links: []At a glance, a Software Template is simple, but it’s powerful. With just one file, you can guide developers along a Golden Path, ensuring consistency, security, and compliance without slowing them down.
Step 1: Defining Input Parameters
When a developer clicks “Choose” on your template, Backstage presents a dynamic web form. This form is generated automatically by reading the parameters block in your YAML.
Backstage uses JSON Schema under the hood to define these forms, making it easy to collect structured input from developers.
Let’s build a simple form that asks:
- The name of the new repository
- Which team will own it
- A description of the service
Here’s how it looks in the YAML:
parameters:
- title: Provide Component Details
required:
- component_id
- owner
properties:
component_id:
title: Name
type: string
description: Unique name of the component (e.g. payment-service)
ui:field: EntityNamePicker # A special Backstage UI component
description:
title: Description
type: string
description: What does this service do?
owner:
title: Owner
type: string
description: Which team owns this?
ui:field: OwnerPicker # A special drop-down pulling groups from the Catalog
ui:options:
allowedKinds:
- GroupBecause we use ui:field: OwnerPicker, developers don’t have to guess their team’s exact ID. Backstage automatically populates a drop-down with teams from the Software Catalog we built in Part 2.
This makes creating new services faster, less error-prone, and fully aligned with your platform’s Golden Path.
Step 2: Utilizing Nunjucks Templating
Before we define the execution steps, it’s important to understand how data flows in Backstage templates.
Everything the developer types into the form is saved into a context variable called parameters. To use these values in your code, scripts, or configs, we leverage the Nunjucks templating language.
If you’ve used Jinja2 in Python or Handlebars in JavaScript, Nunjucks will feel familiar. It lets you safely inject user input into your template using the syntax ${{ }}.
For example, if a developer enters checkout-api as the component_id, you can reference it later like this:
${{ parameters.component_id }}This ensures that user-provided data flows securely and dynamically into every step of your template, making your Golden Path fully automated and error-resistant.
Step 3: Defining the Scaffolder Steps
Now comes the magic. We’ve collected the inputs from our developer — now it’s time to tell the Scaffolder engine exactly what to do.
Get Ramesh | The Platform Engineer’s stories in your inbox
Join Medium for free to get updates from this writer.
A standard template usually follows three chronological steps:
fetch:template– Download a skeleton repository (your boilerplate code) into a temporary workspace.publish:github– Create a new repository on GitHub and push the templated code.catalog:register– Tell the Backstage Catalog to immediately track the new repository.
Here’s what that looks like in YAML:
steps:
# STEP 1: Fetch the skeleton structure
- id: fetch-base
name: Fetch Base Skeleton
action: fetch:template
input:
# Points to a folder containing starter code and a skeletal catalog-info.yaml
url: ./skeleton
# Map form inputs (parameters) into the Nunjucks templating engine
values:
name: '${{ parameters.component_id }}'
description: '${{ parameters.description }}'
owner: '${{ parameters.owner }}'
# STEP 2: Publish the new code to GitHub
- id: publish
name: Publish to GitHub
action: publish:github
input:
allowedHosts: ['github.com']
description: This is ${{ parameters.component_id }}
repoUrl: 'github.com?repo=${{ parameters.component_id }}&owner=your-github-org'
# Optional: Protect the main branch immediately
protectDefaultBranch: true
# STEP 3: Register it in the IDP
- id: register
name: Register in Catalog
action: catalog:register
input:
# Backstage creates the catalog-info.yaml via templating,
# publishes it, and registers it from the new GitHub URL
repoContentsUrl: '${{ steps.publish.output.repoContentsUrl }}'
catalogInfoPath: '/catalog-info.yaml'Here’s what’s happening under the hood:
- Fetch Base Skeleton: Copies your starter project and applies the user’s inputs using Nunjucks templating.
- Publish to GitHub: Automatically creates a repository, pushes code, and optionally protects the main branch.
- Register in Catalog: Immediately tells Backstage to track this new repository, so it appears in your catalog without extra manual steps.
With these three steps, a developer goes from clicking a button to having a fully configured service in minutes — following the Golden Path every time.
Step 4: Outputting the Result
The final piece of a Software Template is the output block. This controls what the developer sees when the progress bar hits 100%.
The goal? Give developers immediate access to the things they need — without hunting for URLs or dashboards.
Here’s an example YAML for the output:
output:
links:
- title: Go to Source Code
url: '${{ steps.publish.output.remoteUrl }}'
- title: Open in Backstage Catalog
icon: catalog
entityRef: '${{ steps.register.output.entityRef }}'When the template finishes:
- One button takes the developer straight to the newly scaffolded GitHub repository.
- Another button drops them directly onto the new Backstage component dashboard.
This small but powerful feature closes the loop, giving instant feedback and making the Golden Path experience smooth, satisfying, and fully self-service.
Register Template
If you’re working with a growing number of templates — especially if you expect that number to increase over time — it’s worth setting up automated discovery.
As we discussed in a previous article, you can configure Discovery to handle this dynamically, so new templates are picked up without manual effort.
Alternatively, if your setup is smaller or more controlled, you can still register templates manually by adding them to the app-config.yaml file under the catalog section.
catalog:
locations:
- type: url
target: https://github.com/username/repo/blob/main/template.yamlCreating a New Project with Your Template
Once your Software Template is ready, developers can use it directly from the Backstage UI. Here’s how the process works:
1. Navigate to the Templates Catalog
Head over to the Templates section in Backstage. You should see your newly created template listed, along with its title and description.
2. Click “Choose”
Click the “Choose” button on your template. Backstage will open the dynamic form we defined in the parameters block.
3. Fill Out the Form
Enter the required details:
- Name: The name of your new service or component
- Description: A short description of what the service does
- Owner: Select the team responsible for this service from the dropdown
Backstage will validate required fields before moving on.
4. Click “Create”
Once the form is complete, click “Create”. Backstage will execute all the steps defined in your template:
- Scaffold the code from your skeleton repository
- Publish it to GitHub
- Register it in the Backstage catalog
5. Access Your New Service
When the progress bar reaches 100%, the output block provides immediate buttons:
- Go to Source Code — Takes you directly to the new GitHub repository
- Open in Backstage Catalog — Opens your newly created component dashboard
With just a few clicks, your developers have a fully scaffolded, compliant, and cataloged service, all following the Golden Path.
Wrapping Up Part 4
Congratulations! You’ve successfully defined a Golden Path.
Instead of spending five days configuring a new repository, a developer can now fill out a three-question form, grab a cup of coffee, and return to a fully scaffolded, compiling, and cataloged microservice — ready to go.
But a developer portal is about more than just creating code. It’s also about actively maintaining it and keeping your platform healthy, consistent, and easy to navigate.
Try It Yourself
Ready to pave your own Golden Path? Open Backstage, create a template using the steps above, and scaffold your first service.
💡 Tip: Share your template or improvements in the comments — your fellow developers would love to see how you automate your workflow!
Want to keep leveling up your Backstage skills? Make sure to follow this series for the next installment: [Part 5: Customizing UI with MUI], where we’ll turn your developer portal into a fully polished, user-friendly experience.









