Skip to content

<Template>

The <Template> block generates files from a Gruntwork Boilerplate template directory. It renders a form for any variables defined in the template, and saves generated files to the workspace.

<Template id="vpc-setup" path="templates/vpc" />

This loads the boilerplate.yml file from templates/vpc/boilerplate.yml (relative to your runbook file), renders a form for the variables, and generates files when the user clicks “Generate”.

Template and TemplateInline both render Boilerplate templates, but they serve different purposes:

Feature<Template><TemplateInline>
Template sourceDirectory with boilerplate.ymlInline in runbook
Form renderedYes, from boilerplate.ymlNo form (uses Inputs)
File generationAlways saves to workspaceOptional (generateFile={true})
Use caseGenerate files from template directoriesShow preview of single files inline

Use <Template> when you have a full Boilerplate template directory with multiple files and a boilerplate.yml configuration. Use <TemplateInline> when you want to show a quick inline preview or generate a single file without a separate template directory.

  • id (string) - Unique identifier for this component. Used to reference this Template’s variables from other blocks.
  • path (string) - Path to the boilerplate template directory, relative to the runbook file. The directory must contain a boilerplate.yml file.
  • inputsId (string | string[]) - ID of Inputs or Template block(s) to import variable values from. When multiple IDs are provided as an array, variables are merged in order (later IDs override earlier ones).
  • target ("generated" | "worktree") - Where template output is written. Defaults to "generated", which writes to the standard generated files directory ($GENERATED_FILES). Set to "worktree" to write directly into the active git worktree (the most recently cloned repo via <GitClone>). Requires a <GitClone> block to have run first.

The path prop should point to a directory containing a boilerplate.yml file and any template files:

<Template id="my-template" path="templates/vpc" />

Expected directory structure:

templates/vpc/
├── boilerplate.yml # Variable definitions (required)
├── arbitrary_template_files.txt # Template file

The boilerplate.yml file defines the variables that will be collected from the user. Template files use Boilerplate’s Go template syntax for variable substitution.

There are several ways to provide variables to a Template.

The Template displays a form with all variables defined in its boilerplate.yml:

<Template id="vpc-setup" path="templates/vpc" />

Import variables from a separate Inputs block:

<Inputs id="config">
```yaml
variables:
- name: Environment
type: enum
options: [dev, staging, prod]
default: dev
- name: Region
type: string
default: us-east-1
```
</Inputs>
<Template id="vpc" path="templates/vpc" inputsId="config" />

Variables from config are merged with the template’s own variables. Shared variables become read-only in the Template form.

You can reference multiple Inputs blocks by passing an array of IDs. Variables are merged in order, with later IDs overriding earlier ones:

<Inputs id="org-config">
```yaml
variables:
- name: OrgName
type: string
```
</Inputs>
<Inputs id="env-config">
```yaml
variables:
- name: Environment
type: enum
options: [dev, prod]
```
</Inputs>
<Template
id="infrastructure"
path="templates/infra"
inputsId={["org-config", "env-config"]}
/>

When a Template references external inputs via inputsId, variables fall into three categories:

CategoryDescriptionForm Behavior
Local-onlyExists only in the template’s boilerplate.ymlEditable
Imported-onlyExists only in imported sourcesNot shown, but passed to template
SharedExists in both template and imported sourcesRead-only, live-synced

Template files use Boilerplate’s Go template syntax:

main.tf
resource "aws_vpc" "main" {
cidr_block = "{{ .CidrBlock }}"
tags = {
Name = "{{ .VpcName }}"
Environment = "{{ .Environment }}"
}
}
{{- if .EnableFlowLogs }}
resource "aws_flow_log" "main" {
vpc_id = aws_vpc.main.id
# ...
}
{{- end }}

Templates can reference outputs from Command or Check blocks that have already run. This allows you to generate files based on dynamic values produced by previous steps.

Access block outputs using the _blocks namespace:

# In your template file
account_id = "{{ ._blocks.create_account.outputs.account_id }}"
region = "{{ ._blocks.create_account.outputs.region }}"

When a Template loads, Runbooks automatically scans the template files for {{ ._blocks.*.outputs.* }} patterns. If those outputs don’t exist yet:

  1. A warning is displayed showing which blocks need to run first
  2. The “Generate” button is disabled until the required blocks have executed

Example: Using Command Outputs in a Template

Section titled “Example: Using Command Outputs in a Template”
## Step 1: Create Account
<Command
id="create-account"
path="scripts/create-account.sh"
title="Create AWS Account"
/>
## Step 2: Generate Configuration
This template uses the account ID from Step 1:
<Template
id="account-config"
path="templates/account-config"
/>

And in templates/account-config/main.tf:

# Values populated from the create-account Command's outputs
locals {
account_id = "{{ ._blocks.create_account.outputs.account_id }}"
region = "{{ ._blocks.create_account.outputs.region }}"
}
resource "aws_iam_account_alias" "alias" {
account_alias = "my-org-${local.account_id}"
}

You can use both standard inputs (from <Inputs> blocks) and block outputs in the same template:

# Standard inputs from Inputs block
environment = "{{ .Environment }}"
owner = "{{ .Owner }}"
# Block outputs from Command/Check blocks
account_id = "{{ ._blocks.create_account.outputs.account_id }}"

The <Template> block works especially well for generating files from structured templates:

  • Generate infrastructure code: Create Terraform, Terragrunt, or other IaC files based on user inputs.
  • Scaffold projects: Generate project structures with configuration files customized to user preferences.
  • Create configuration files: Generate CI/CD pipelines, Docker Compose files, Kubernetes manifests, or other config files.
  • Multi-file generation: Generate multiple related files that need consistent variable values.

Here’s a complete runbook showing Template with imported variables and validation:

# Deploy a VPC
First, configure your environment:
<Inputs id="env-config">
```yaml
variables:
- name: Environment
type: enum
options: [dev, staging, prod]
default: dev
- name: Region
type: string
default: us-east-1
```
</Inputs>
Now configure your VPC. The Environment and Region will be inherited from above:
<Template id="vpc-setup" path="templates/vpc" inputsId="env-config" />
/>