Boilerplate is a tool for generating files and folders ("boilerplate") from a set of templates.
Example use cases:
See Introducing Boilerplate for a quick introduction.
Create a folder called website-boilerplate
and put a file called boilerplate.yml
in it:
variables:
- name: Title
- name: WelcomeText
description: Enter the welcome text for the website
- name: ShowLogo
description: Should the website show the logo?
type: bool
default: true
This file defines 3 variables: Title
, WelcomeText
, and ShowLogo
. When you run Boilerplate, it will prompt
the user for each one.
Next, create an index.html
in the website-boilerplate
folder that uses these variables using Go
Template syntax:
<html>
<head>
<title>{{.Title}}</title>
</head>
<body>
<h1>{{.WelcomeText}}</h1>
{{if .ShowLogo}}<img src="https://github.com/gruntwork-io/boilerplate/raw/master/logo.png">{{end}}
</body>
</html>
Copy an image into the website-boilerplate
folder and call it logo.png
.
Finally, run boilerplate
, setting the --template-url
to website-boilerplate
and --output-folder
to the path
where you want the generated code to go:
boilerplate --template-url /home/ubuntu/website-boilerplate --output-folder /home/ubuntu/website-output
Title
Enter a value [type: string]: Boilerplate Example
WelcomeText
Enter the welcome text for the website
Enter a value [type: string]: Welcome!
ShowLogo
Should the website show the logo?
Enter a [type: bool]: true
Generating /home/ubuntu/website-output/index.html
Copying /home/ubuntu/website-output/logo.png
Boilerplate copies any files from the --template-url
into the --output-folder
, passing them through the
Go Template engine along the way. After running the command above, the
website-output
folder will contain a logo.png
(unchanged from the original) and an index.html
with the
following contents:
<html>
<head>
<title>Boilerplate</title>
</head>
<body>
<h1>Welcome!</h1>
<img src="https://github.com/gruntwork-io/boilerplate/raw/master/logo.png">
</body>
</html>
You can also run Boilerplate non-interactively, which is great for automation:
boilerplate \
--template-url /home/ubuntu/website-boilerplate \
--output-folder /home/ubuntu/website-output \
--non-interactive \
--var Title="Boilerplate Example" \
--var WelcomeText="Welcome!" \
--var ShowLogo="true"
Generating /home/ubuntu/website-output/index.html
Copying /home/ubuntu/website-output/logo.png
Of course, Boilerplate can be used to generate any type of project, and not just HTML, so check out the examples folder for more examples and the Working with Boilerplate section for full documentation.
Download the latest binary for your OS here.
You can find older versions on the Releases Page.
boilerplate.yml
file and makes those variables available to your project templates during copying.When you run Boilerplate, it performs the following steps:
boilerplate.yml
file in the folder specified by the --template-url
option to find all defined
varaibles.--var
and --var-file
options that were passed in and prompting the user
for the rest (unless the --non-interactive
flag is specified).--template-url
to --output-folder
, running each non-binary file through the Go
Template engine with the map of variables as the data structure.Learn more about boilerplate in the following sections:
The boilerplate
binary supports the following options:
--template-url URL
(required): Generate the project from the templates in URL
. This can be a local path, or a
go-getter compatible URL for remote templates (e.g.,
git@github.com:gruntwork-io/boilerplate.git//examples/for-learning-and-testing/include?ref=master
).--output-folder
(required): Create the output files and folders in FOLDER
.--non-interactive
(optional): Do not prompt for input variables. All variables must be set via --var
and
--var-file
options instead.--var NAME=VALUE
(optional): Use NAME=VALUE
to set variable NAME
to VALUE
. May be specified more than once.--var-file FILE
(optional): Load variable values from the YAML file FILE
. May be specified more than once.--missing-key-action ACTION
(optional): What to do if a template looks up a variable that is not defined. Must
be one of: invalid
(render the text "zero
(render the zero value for the variable), or error
(return an error and exit immediately). Default: error
.--missing-config-action ACTION
(optional): What to do if a template folder does not have a boilerplate.yml
file.
Must be one of: exit
(return an error and exit immediately) or ignore
(log a warning and process the template
folder without any variables). Default: exit
.--disable-hooks
: If this flag is set, no hooks will execute.--disable-shell
: If this flag is set, no shell
helpers will execute. They will instead return the text "replace-me".--disable-dependency-prompt
(optional): Do not prompt for confirmation to include dependencies. Has the same effect as
--non-interactive, without disabling variable prompts. Default: false
.--help
: Show the help text and exit.--version
: Show the version and exit.Some examples:
Generate a project in ~/output from the templates in ~/templates:
boilerplate --template-url ~/templates --output-folder ~/output
Generate a project in ~/output from the templates in ~/templates, using variables passed in via the command line:
boilerplate --template-url ~/templates --output-folder ~/output --var "Title=Boilerplate" --var "ShowLogo=false"
Generate a project in ~/output from the templates in ~/templates, using variables read from a file:
boilerplate --template-url ~/templates --output-folder ~/output --var-file vars.yml
Generate a project in ~/output from the templates in this repo's include
example dir, using variables read from a file:
boilerplate --template-url "git@github.com:gruntwork-io/boilerplate.git//examples/for-learning-and-testing/include?ref=master" --output-folder ~/output --var-file vars.yml
The boilerplate.yml
file is used to configure boilerplate
. The file is optional. If you don't specify it, you can
still use Go templating in your templates so long as you specify the --missing-config-action ignore
option, but no
variables or dependencies will be available.
boilerplate.yml
uses the following syntax:
required_version: <VERSION_CONSTRAINT>
variables:
- name: <NAME>
description: <DESCRIPTION>
type: <TYPE>
options:
- <CHOICE>
- <CHOICE>
default: <DEFAULT>
reference: <NAME>
dependencies:
- name: <DEPENDENCY_NAME>
template-url: <FOLDER>
output-folder: <FOLDER>
skip: <CONDITION>
dont-inherit-variables: <BOOLEAN>
for_each: <LIST>
for_each_reference: <NAME>
variables:
- name: <NAME>
description: <DESCRIPTION>
type: <TYPE>
default: <DEFAULT>
hooks:
before:
- command: <CMD>
args:
- <ARG>
env:
<KEY>: <VALUE>
skip: <CONDITION>
after:
- command: <CMD>
args:
- <ARG>
env:
<KEY>: <VALUE>
skip: <CONDITION>
partials:
- <GLOB>
- <GLOB>
Here's an example:
variables:
- name: Description
description: Enter the description of this template
- name: Version
description: Enter the version number that will be used by the docs dependency
- name: Title
description: Enter the title for the dependencies example
- name: WelcomeText
description: Enter the welcome text used by the website dependency
- name: ShowLogo
description: Should the webiste show the logo (true or false)?
type: bool
default: true
dependencies:
- name: docs
template-url: ../docs
output-folder: ./docs
variables:
- name: Title
description: Enter the title of the docs page
- name: website
template-url: ../website
output-folder: ./website
variables:
- name: Title
description: Enter the title of the website
skip_files:
- path: .ignore-me
- path: subfolder/README.md
if: {{ not .ShowLogo }}
engines:
- path: subfolder/foo.json.jsonnet
template_engine: jsonnet
partials:
- ../html/*.html
- ../css/*.css
- ../other/somefile.html
Required Version: A version constraint string in the same format as Terraform that can be used to specify what versions of Boilerplate are supported by the config.
Variables: A list of objects (i.e. dictionaries) that define variables. Each variable may contain the following keys:
name
(Required): The name of the variable.description
(Optional): The description of the variable. boilerplate
will show this description to the user when
prompting them for a value.type
(Optional): The type of the variable. Must be one of: string
, int
, float
, bool
, map
, list
, enum
.
If unspecified, the default is string
.options
(Optional): If the type
is enum
, you can specify a list of valid options. Each option must be a string.default
(Optional): A default value for this variable. The user can just hit ENTER at the command line to use the
default value, if one is provided. If running Boilerplate with the --non-interactive
flag, the default is
used for this value if no value is provided via the --var
or --var-file
options.reference
(Optional): The name of another variable whose value should be used for this one.See the Variables section for more info.
Dependencies: A list of objects (i.e. dictionaries) that define other boilerplate
templates to execute before
executing the current one. Each dependency may contain the following keys:
name
(Required): A unique name for the dependency.template-url
(Required): Run boilerplate
on the templates in this folder. This path is relative to the
current template.output-folder
(Required): Create the output files and folders in this folder. This path is relative to the output
folder of the current template.skip
(Optional): Skip this dependency if this condition, which can use Go templating syntax and
boilerplate variables, evaluates to the string true
. This is useful to conditionally enable or disable
dependencies.dont-inherit-variables
(Optional): By default, any variables already set as part of the current boilerplate.yml
template will be reused in the dependency, so that the user is not prompted multiple times for the same variable. If
you set this option to false
, then the variables from the parent template will not be reused.variables
: If a dependency contains a variable of the same name as a variable in the root boilerplate.yml
file,
but you want the dependency to get a different value for the variable, you can specify overrides here. Note that these
variables will not influence the boilerplate prompts.var_files
: If you want to set the variables for the dependency based on a var file, you can provide a list of var
file paths to include. The path is assumed to be relative to the current boilerplate.yml, but it is recommended to use
the templateFolder
helper function to be explicit. Note that the order of preference for variables are (top most
have highest precedence - aka override all):
variables
field of the dependency).for_each
: If you set this to a list of values, boilerplate
will loop over each value, and render this dependency
once for each value. This allows you to dynamically render a dependency multiple times based on user input. The
current value in the loop will be available as the variable __each__
, available to both your Go templating and
in other dependencies
params: e.g., you could reference {{ .__each__ }}
in output-folder
to render to each
iteration to a different folder.for_each_reference
: The name of another variable whose value should be used as the for_each
value.See the Dependencies section for more info.
Partials: Use partials to include reusable templates. Partials are defined using a list of glob patterns.
filepath.Glob
functionSee the Partials section for more info.
Skip Files: Use skip_files to specify files in the template folder that should not be rendered. The path
field
is the relative path from the template folder root (where the boilerplate.yml
file is defined) of the file that should
be excluded. You can conditionally skip the file using the if
field, which should either be a YAML boolean value
(true
or false
), or Go templating syntax (which can use the boilerplate variables) that evaluates to the string
values "true"
or "false"
.
See the Skip Files section for more info.
Engines: Use engines to specify files in the template folder that should be rendered with an alternative
templating engine. The path
field is the relative path from the template folder root (where the boilerplate.yml
file
is defined) of the file that should use the alternative template engine.
See the Alternative Template Engines (EXPERIMENTAL) section for more info.
Hooks: Boilerplate provides hooks to execute arbitrary shell commands. There are two types of hooks:
before
(Optional): A list of scripts to execute before any template rendering has started.after
(Optional): A list of scripts to execute after all template rendering has completed.See the Hooks section for more info.
You must provide a value for every variable defined in boilerplate.yml
, or project generation will fail. There are
four ways to provide a value for a variable:
--var
option(s) you pass in when calling boilerplate. Example:
boilerplate --var Title=Boilerplate --var ShowLogo=false
. To specify a complex type like a map or a list on the
command-line, use YAML syntax (preferably the shorthand variety to keep it a one-liner). For example
--var foo='{key: "value"}' --var bar='["a", "b", "c"]'
. If you want to specify the value of a
variable for a specific dependency, use the <DEPENDENCY_NAME>.<VARIABLE_NAME>
syntax. For example:
boilerplate --var Description='Welcome to my home page!' --var about.Description='About Us' --var ShowLogo=false
.--var-file
option(s) you pass in when calling boilerplate. Example: boilerplate --var-file vars.yml
. The vars
file must be a simple YAML file that defines key, value pairs, where the key is the name of a variable (or
<DEPENDENCY_NAME>.<VARIABLE_NAME>
for a variable in a dependency) and the value is the value to set for that
variable. Example:
Title: Boilerplate
ShowLogo: false
Description: Welcome to my home page!
about.Description: Welcome to my home page!
ExampleOfAMap:
key1: value1
key2: value2
ExampleOfAList:
- value1
- value2
--var
or --var-file
flags, Boilerplate will interactively prompt
the user to provide a value. Note that the --non-interactive
flag disables this functionality.boilerplate.yml
. The final fallback is the optional default
that you can include as part of
the variable definition in boilerplate.yml
.Note that variables can reference other variables using Go templating syntax:
variables:
- name: Foo
default: foo
- name: Bar
default: "{{ .Foo }}-bar"
If you rendered {{ .Bar }}
with the variables above, you would get foo-bar
. Note that this will always
return a string. If you want to reference another variable of a non-string type (e.g. a list), use the reference
keyword:
variables:
- name: Foo
type: list
default:
- 1
- 2
- 3
- name: Bar
type: list
reference: Foo
In the example above, the Bar
variable will be set to the same (list) value as Foo
.
Specifying dependencies within your boilerplate.yml
files allows you to chain multiple boilerplate
templates
together. This allows you to create more complicated projects from simpler pieces.
Note the following:
boilerplate.yml
in folder A
can include folder B in its dependencies
list, the boilerplate.yml
in folder B can include folder C in its
dependencies
list, and so on.boilerplate.yml
and any variables with
the same name in the boilerplate.yml
files of your dependencies
list will reuse those variables instead of
prompting the user for the same value again.variable
blocks for each dependency and boilerplate
will
prompt you for each of those variables separately from the root ones. You can also use the
<DEPENDENCY_NAME>.<VARIABLE_NAME>
syntax as the name of the variable with the -var
flag and inside of a var file
to provide a value for a variable in a dependency.template-url
and output-folder
parameters of your
dependencies. This allows you to use specify the paths to your template and output folders dynamically.Conditional dependencies: You can enable or disable a dependency using the skip
parameter, which supports Go
templating syntax and boilerplate variables. If the skip
parameter evaluates to the string true
, the
dependency will be skipped; otherwise, it will be rendered. Example:
variables:
- name: Foo
type: bool
- name: Bar
type: bool
dependencies:
- name: conditional-dependency-example
template-url: ../foo
output-folder: foo
# Skip this dependency if both .Foo and .Bar are set to true
skip: "{{ and .Foo .Bar }}"
Looping over dependencies: You can render a dependency multiple times, dynamically, based on user input, via the
for_each
or for_each_reference
parameter. Example:
variables:
- name: environments
description: The environments to deploy into (e.g., dev, stage, prod)
type: list
default:
- dev
- stage
- prod
dependencies:
- name: loop-dependency-example
template-url: ../terraform
# Render this dependency once for each environment the user specifies
for_each_reference: environments
# Render the dependency to an output folder that includes the environment name
output-folder: "live/{{ .__each__ }}"
variables:
- name: ServerName
description: The name to use for the EC2 instance (for its Name tag)
type: string
# Use the environment name in the server name
default: "example-{{ .__each__ }}"
--non-interactive
is set, dependencies will be included automatically, so long as skip
is false. If you'd
like to keep interactive mode enabled, but disable dependency confirmation, set --disable-dependency-prompt
.You can specify hooks
in boilerplate.yml
to tell Boilerplate to execute arbitrary shell commands.
Note the following:
before
hook allows you to run scripts before Boilerplate has started rendering.after
hook allows you to run scripts after Boilerplate has finished rendering.Each hook consists of a command
to execute (required), a list of args
to pass to that command (optional),
a map of environment variables in env
to set for the command (optional), and the working directory dir
in which
to run the command (optional). Example:
before:
- command: echo
args:
- Hello
- World
env:
FOO: BAR
dir: "/foo/bar"
You can use Go templating syntax in command
, args
, env
, and dir
. For example, you can pass Boilerplate
variables to your scripts as follows:
before:
- command: foo.sh
args:
- {{ .SomeVariable }}
- {{ .AnotherVariable }}
By default, Boilerplate runs your command
with the working directory set to the --template-url
option. You can
override this with the dir
parameter. For example, here is how you can set it to a sub-folder of the output folder:
after:
- command: some-command
dir: "{{ outputFolder }}/foo/bar"
skip
(Optional): Skip this hook if this condition, which can use Go templating syntax and
boilerplate variables, evaluates to the string true
. This is useful to conditionally enable or disable
dependencies.shell
helper in template helpers.You can specify files that should be excluded from the rendered output using the skip_files
section in
boilerplate.yml
. This is most useful when you have templates that need to conditionally exclude files from the
rendered folder list.
The skip_files
section is a list of objects with the fields path
, not_path
, and if
, where one of path
or
not_path
is required. When path
is set, all files that match the path
attribute will be skipped, while when
not_path
is set, all files that DO NOT match the not_path
attribute are skipped (in other words, only paths that
match not_path
are kept).
if
can be used to conditionally skip a file from the template folder, and it defaults to true
. That is, when if
is
omitted, the file at the path is always excluded from the output. Note that path
and not_path
are always the
relative path from the template root.
All three attributes (path
, not_path
, and if
) support Go templating syntax with access to boilerplate
variables and template helpers.
Consider the following boilerplate template folder:
.
├── boilerplate.yml
├── BOILERPLATE_README.md
└── docs
├── README_WITH_ENCRYPTION.md
└── README_WITHOUT_ENCRYPTION.md
Suppose that you wanted to conditionally select which README to render based on some variable. You can use skip_files
to implement this logic:
variables:
- name: UseEncryption
type: bool
skip_files:
- path: "BOILERPLATE_README.md"
- path: "docs/README_WITH_ENCRYPTION.md"
if: "{{ not .UseEncryption }}"
- path: "docs/README_WITHOUT_ENCRYPTION.md"
if: "{{ .UseEncryption }}"
- not_path: "docs/**/*"
if: "{{ .DocsOnly }}"
This will:
BOILERPLATE_README.md
.docs/README_WITHOUT_ENCRYPTION.md
if UseEncryption
is set to true
.docs/README_WITH_ENCRYPTION.md
if UseEncryption
is set to false
.DocsOnly
is set to true
, only render the docs
folder.For a more concise specification, you can use glob syntax in the path
to match multiple paths in one entry:
skip_files:
- path: "docs/**/*"
Boilerplate puts all the variables into a Go map where the key is the name of the variable and the value is what
the user provided. It then starts copying files from the --template-url
into the --output-folder
, passing each
non-binary file through the Go Template engine, with the variable map as a data structure.
For example, if you had a variable called Title
in your boilerplate.yml
file, then you could access that variable
in any of your templates using the syntax {{.Title}}
. You can also use Go template syntax to do
if-statements, for loops, and use the provided template helpers.
You can even use Go template syntax and boilerplate variables in the names of your files and folders. For example, if
you were using boilerplate
to generate a Java project, your template folder could contain the path
com/{{.PackageName}}/MyFactory.java
. If you run boilerplate
against this template folder and enter
"gruntwork" as the PackageName
, you'd end up with the file com/gruntwork/MyFactory.java
.
Boilerplate allows you to specify a set of validations when defining a variable. When a user is prompted for a variable that has validations defined, their input must pass all defined validations. If the user's input does not pass all validations, they'll be presented with real-time feedback on exactly which rules their submission is failing. Once a user's submission passes all defined validations, Boilerplate will accept their submitted value.
Here's an example prompt for a variable with validations that shows how invalid submissions are handled:
Here's an example demonstating how to specify validations when defining your variables:
variables:
- name: CompanyName
description: Enter the name of your organization.
default: ""
type: string
validations:
- required
- length-5-22
- alphanumeric
This boilerplate.yml
snippet defines a variable, CompanyName
which:
Currently supported validations
Boilerplate uses the go-ozzo/ozzo-validation
library. The following validations are currently supported:
Boilerplate allows you to define the relative order in which a set of variables should be presented to the user when prompting for human input.
Here's an example demonstrating how to define the relative order of a set of variables:
variables:
- name: WebsiteURL
order: 0
description: Enter the URL to your homepage
- name: ImagePath:
order: 1
description: Enter the full filepath to your logo image
- name: ProfileName
order: 2
description: Enter the display name for your user
Boilerplate has experimental support for the following alternative template engines:
To specify an alternative template engine, you can use the engines
directive to provide a path glob that matches the
files that should be fed through the alternative engine. For example, the following boilerplate configuration makes it
so that any file with the .jsonnet
extension will be fed through the jsonnet template engine:
engines:
- path: "**/*.jsonnet"
template_engine: jsonnet
Note that alternative template engines are currently only supported for processing individual files, and can not be used for parsing boilerplate directives in the config file or directory names.
See below for more information on each of the template engines supported:
IMPORTANT: Support for template helpers are limited to the go templating engine at this time. Some limited functions may be available depending on the template engine. See the information for the templating engine to know which functions are supported.
Jsonnet is a data template engine optimized for generating json data. Unlike go templating, jsonnet has many features that make it more friendly to write such as:
When boilerplate processes jsonnet templates, the variables are passed through as a Top Level
Argument under the name boilerplateVars
. This
means that every jsonnet template must be defined in a way to handle the TLA argument. For example:
function(boilerplateVars) {
person: {
name: boilerplateVars.Name,
},
}
Boilerplate will also make available the following helpers as external variables:
templateFolder
: Set to the value of the template working dir. This is the same as what the templateFolder
boilerplate helper function returns.outputFolder
: Set to the value of the output folder where the templates are rendered. This is the same as what the
outputFolder
boilerplate helper function returns.While the jsonnet
template engine does not support the boilerplate helper functions, it does have access to the
Jsonnet standard library. You can also import any libsonnet
library in your
jsonnet template, including those installed with jsonnet-bundlery.
Note that to ensure you can have editor assistance while modifying jsonnet files, the jsonnet template engine in
boilerplate will strip the extension suffix .jsonnet
from the output file path. E.g., if your template folder
contained:
.
├── boilerplate.yml
└── data.json.jsonnet
The output folder will be:
.
└── data.json
Your templates have access to all the standard functionality in Go Template, including conditionals, loops, and functions.
Additionally, boilerplate ships with sprig (version 3.2.1
), the standard
library of template functions. You can view all the functions available in sprig
here. Note that there are some differences for some functions due to backwards
compatibility. Take a look at Deprecated helpers.
Boilerplate also includes several custom helpers that you can access that enhance the functionality of sprig:
snippet <PATH> [NAME]
: Returns the contents of the file at PATH
as a string. If you specify the second argument,
NAME
, only the contents of the snippet with that name will be returned. A snippet is any text in the file
surrounded by a line on each side of the format "boilerplate-snippet: NAME" (typically using the comment syntax for
the language). For example, here is how you could define a snippet named "foo" in a Java file:
String str = "this is not part of the snippet";
// boilerplate-snippet: foo
String str2 = "this is part of the snippet";
return str2;
// boilerplate-snippet: foo
include <PATH> <VARIABLES>
: Returns the contents of the file at PATH
after rendering it through the templating
engine with the provided variables, as a string (unlike snippet
, which returns the contents of the file verbatim).
Use .
to pass the current variables to the included template. E.g:
{{ include "../source-template.snippet" . }}
replaceOne OLD NEW
: Replace the first occurrence of OLD
with NEW
. This is a literal replace, not regex.replaceAll OLD NEW
: Replace all occurrences of OLD
with NEW
. This is a literal replace, not regex.roundInt FLOAT
: Round FLOAT
to the nearest integer. E.g. 1.5 becomes 2.ceilInt FLOAT
: Round up FLOAT
to the nearest integer. E.g. 1.5 becomes 2.floorInt FLOAT
: Round down FLOAT
to the nearest integer. E.g. 1.5 becomes 1.dasherize STRING
: Convert STRING
to a lower case string separated by dashes. E.g. "foo Bar baz" becomes
"foo-bar-baz".camelCaseLower STRING
: Convert STRING
to a camel case string where the first letter is lower case. E.g.
"foo Bar baz" becomes "fooBarBaz".plus NUM NUM
: Add the two numbers. Unlike add in sprig, this
supports float.minus NUM NUM
: Subtract the two numbers. Unlike sub in sprig,
this supports float.times NUM NUM
: Multiply the two numbers. Unlike mul in sprig,
this supports float.divide NUM NUM
: Divide the two numbers. Unlike div in sprig,
this supports float.numRange START END INCREMENT
: Generate a slice from START to END, incrementing by INCREMENT. This provides a simple
way to do a for-loop over a range of numbers.keysSorted MAP
: Return a slice that contains all the keys in the given MAP in alphanumeric sorted order. Use the
built-in Go template helper .index
to look up these keys in the map.shell CMD ARGS...
: Execute the given shell command, passing it the given args, and render whatever that command
prints to stdout. The working directory for the command will be set to the directory of the template being rendered,
so you can use paths relative to the file from which you are calling the shell
helper. Any argument you pass of the
form ENV:KEY=VALUE
will be set as an environment variable for the command rather than an argument. For another way
to execute commands, see hooks.templateFolder
: Return the value of the template working dir. This is the value of the --template-url
command-line
option if local template, or the download dir if remote template. Useful for building relative paths.outputFolder
: Return the value of the --output-folder
command-line option. Useful for building relative paths.envWithDefault NAME DEFAULT
: Render the value of environment variable NAME
. If that environment variable is empty or not
defined, render DEFAULT
instead.pathExists PATH
: Returns true if the given path exists on the file system.templateIsDefined NAME
: Returns a boolean indicating if template called NAME
is known. Use this to conditionally
include one boilerplate template with another. Most often useful along with partials.toYaml
: Encodes an input variable as a YAML string. Similar to the toJson
function in sprig.These helpers are deprecated. They are currently available for backwards compatibility, but may be removed in future versions. Please use the alternative supported forms listed in the description.
downcase STRING
: Same functionality as lower in sprig.upcase STRING
: Same functionality as upper in sprig.capitalize STRING
: Same functionality as title in sprig.snakeCase STRING
: Same functionality as snakecase in sprig.camelCase STRING
: Same functionality as camelcase in sprig.The following functions overlap with sprig, but have different functionality. There is an equivalent function listed above under a different name. These point to the boilerplate implementations for backwards compatibility. Please migrate to using the new naming scheme, as they will be updated to use the sprig versions in future versions of boilerplate.
round
: In boilerplate, round
returns the integer form as opposed to float. E.g {{ round 123.5555 }}
will return
124
. The following supported alternative functions are available:
roundFloat
: The sprig version of round, which supports
arbitrary decimal rounding. E.g {{ round 123.5555 3 }}
returns 123.556
. Note that {{ round 123.5555 0 }}
returns 124.0
.roundInt
: Another name for the boilerplate version of round
. Use this if you would like to keep old behavior.ceil
and floor
: In boilerplate, ceil
and floor
return integer forms as opposed to floats. E.g {{ ceil 1.1 }}
returns 2
, as opposed to 2.0
in the sprig version. The following supported alternative functions are
available:
env
: In boilerplate, env
supports returning a default value if the environment variable is not defined. The
following supported alternative functions are available:
readEnv
: The sprig version of env. This always returns empty
string if the environment variable is undefined.envWithDefault
: Another name for the boilerplate version of env
. Use this if you would like to keep old
behavior.keys
: In boilerplate, keys
returns the keys of the map in sorted order. The following supported alternative
functions are available:
keysUnordered
: The sprig version of keys. This returns the
list of keys in no particular order, and there is no guarantee that the order of the returned list is consistent.keysSorted
: Another name for the boilerplate version of keys
. Use this if you would like to keep old
behavior.replace
: In boilerplate, replace
only replaces the first occurrence in the string, as opposed to all occurrences
as in sprig. The following supported alternative functions are available:
replaceAll
: The sprig version of replace.replaceOne
: Another name for the boilerplate version of replace
. Use this if you would like to keep old
behavior.slice
: In boilerplate, slice
returns a list of numbers in the provided range. E.g {{ slice 1 5 1 }}
returns the list [1, 2, 3, 4]
. The following supported alternative functions are available:
sliceList
: The sprig version of slice, which returns the
slice of the given list. E.g {{ slice list n m }}
returns list[n:m]
.numRange
: Another name for the boilerplate version of slice
. Use this if you would like to keep old
behavior.trimPrefix
and trimSuffix
: In boilerplate, trimPrefix
and trimSuffix
takes the base string first. E.g
{{ trimPrefix hello-world hello }}
returns -world
. The following supported alternative functions are
available:
trimPrefixSprig
and trimSuffixSprig
: The sprig version of
trimPrefix and
trimSuffix. Unlike the boilerplate version, this
takes the trim text first so that you can pipeline the trimming. E.g {{ "hello-world" | trimPrefix "hello" }}
returns {{ -world }}
.trimPrefixBoilerplate
and trimSuffixBoilerplate
: Another name for the boilerplate versions of trimPrefix
and trimSuffix
. Use this if you would like to keep old behavior.Partials help to keep templates DRY. Using partials, you can define templates in external files, and then use those templates over and over again in other templates. Partials are common among templating engines, such as in Hugo.
Let's start with a simple example. In an HTML document, we might want to have a common set of meta
tags to reuse throughout our site:
<html>
<head>
<meta charset="UTF-8">
<meta name="author" content="Gruntwork">
</head>
<body>
<h1>Welcome to this page!</h1>
<img src="https://github.com/gruntwork-io/boilerplate/raw/master/logo.png">
</body>
</html>
Rather than add these tags in a <head>
section within each and every file, we could define a partial, then reuse it throughout the site.
We define the header in partials/header.html
:
{{ define "header" }}
<head>
<meta charset="UTF-8">
<meta name="author" content="Gruntwork">
</head>
{{ end }}
Then we set up the structure in templates/boilerplate.yml
:
partials:
- ../partials/*.html
In templates/page.html
:
<html>
{{ template "header" }}
<body>
<h1>Welcome to this page!</h1>
<img src="https://github.com/gruntwork-io/boilerplate/raw/master/logo.png">
</body>
</html>
The contents of the header
template will be rendered within page.html
and any other page in which we call the header partial.
Let's see a slightly more involved example.
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Welcome to this page!</h1>
<img src="https://github.com/gruntwork-io/boilerplate/raw/master/logo.png">
</body>
</html>
The example above shows the HTML for a web page, with a title, a welcome message, and a logo. Now, if we wanted to have another page showing a different title and body, we'd have to duplicate all of that content.
In the example below, we'll create a partial that represents the basic layout of the site, then reuse that layout for each page. First, we create a directory structure to keep everything organized:
.
├── partials
│ └── layout.html
└── template
├── about
│ ├── about.html
│ └── boilerplate.yml
└── root
├── boilerplate.yml
└── index.html
In partials/layout.html
, we create the basic page layout:
{{ define "basic_layout" }}
<html>
<head>
<title>{{ .Title }}</title>
</head>
<body>
{{ template "body" . }}
</body>
</html>
{{ end }}
Now, in each of the pages on the site, we can reuse this layout. For example, from the site's root, we want the welcome
page. We create the boilerplate.yml
first:
partials:
- ../../partials/*.html
variables:
- name: Title
description: A title for the page.
default: "Welcome!"
Now we can use the layout within our index.html
:
{{- define "body" -}}
<h1>This is index.html.</h1>
<img src="https://github.com/gruntwork-io/boilerplate/raw/master/logo.png">
{{- end -}}
{{- template "basic_layout" . -}}
When we run boilerplate
, basic_layout
template will be rendered with the contents of the index.html
. Then we can
use the same layout for the about page, with its corresponding boilerplate.yml
.
Contents of about/boilerplate.yml
:
partials:
- ../../partials/*.html
variables:
- name: Title
description: A title for the page.
default: "About"
about/about.html
:
{{- define "body" -}}
<h1>This is about.html.</h1>
{{- end -}}
{{- template "basic_layout" . -}}
Partials do not need to be located in a magic partials
directory. Partials can be located anywhere and referred to using relative
paths.
The list of partials is a glob that can match multiple files. The content of all of the files that match the globs will be parsed when rendering the final template. For example, you could match many HTML files at once with:
partials:
- ../../html/*.html
- ../../css/*.css
You can use the template definitions from any of the included partials throughout your templates.
You can use Go templating syntax in partial paths. For example, you can define a convenenience variable for a relative path to make the paths slightly easier to read:
variables:
- name: TemplatesRoot
description: A convenience variable identify the relative path to the root of the templates directory.
default: ../../../../
partials:
- "{{ .TemplatesRoot }}/html/*.html"
- "{{ .TemplatesRoot }}/css/*.css"
Before creating Boilerplate, we tried a number of other project generators, but none of them met all of our requirements. We list these alternatives below as a thank you to the creators of those projects for inspiring many of the ideas in Boilerplate and so you can try out other projects if Boilerplate doesn't work for you:
cookiecutter.json
file is quite limited in what you can do.This code is released under the Mozilla Public License Version 2.0. Please see LICENSE and NOTICE for more details.
Copyright © 2016 Gruntwork, Inc.