---
title: Variables
sidebar:
  order: 2
description: Variable types, defaults, validations, and ordering.
---

import { Aside } from '@astrojs/starlight/components';

Variables are the primary way to parameterize your templates. They are defined in `boilerplate.yml` and their values
are provided interactively, via CLI flags, or from YAML files.

## Variable Definition

```yaml
variables:
  - name: ProjectName
    description: The name of the project
    type: string
    default: "my-project"
    order: 1
    validations:
      - required
      - length(3, 50)
```

### Fields

| Field | Required | Description |
|-------|----------|-------------|
| `name` | Yes | The variable name, used in templates as `{{ "{{" }} .Name {{ "}}" }}` |
| `description` | No | Human-readable description shown during interactive prompts |
| `type` | No | One of: `string`, `int`, `float`, `bool`, `list`, `map`, `enum`. Defaults to `string` |
| `default` | No | Default value if the user doesn't provide one |
| `options` | Enum only | List of allowed values for `enum` type |
| `order` | No | Integer controlling the order variables are prompted (lower = first) |
| `reference` | No | Name of another variable to reference for complex types |
| `validations` | No | List of validation rules |
| `confirm` | No | If `true`, prompt the user to confirm the default in interactive mode (see [Defaults in Interactive Mode](#defaults-in-interactive-mode)) |

## Variable Types

### `string`

The default type. Accepts any text value.

```yaml
- name: Name
  type: string
  default: "hello"
```

### `int`

An integer value.

```yaml
- name: Port
  type: int
  default: 8080
```

### `float`

A floating-point number.

```yaml
- name: Ratio
  type: float
  default: 0.75
```

### `bool`

A boolean (`true` or `false`).

```yaml
- name: EnableFeature
  type: bool
  default: true
```

### `list`

An ordered list of values. Provide via CLI as YAML syntax:

```yaml
- name: Tags
  type: list
  default:
    - tag1
    - tag2
```

CLI: `--var 'Tags=["web", "api"]'`

### `map`

A key-value map. Provide via CLI as YAML syntax:

```yaml
- name: Config
  type: map
  default:
    key1: value1
    key2: value2
```

CLI: `--var 'Config={host: "localhost", port: "8080"}'`

### `enum`

A constrained set of choices. The `options` field is required.

```yaml
- name: Environment
  type: enum
  options:
    - dev
    - staging
    - production
  default: dev
```

## Validations

Validations run in real-time during interactive prompts, showing which rules pass or fail as the user types.

| Validation | Description |
|-----------|-------------|
| `required` | Value cannot be empty |
| `length(min, max)` | Character count must be within range (e.g., `length(3, 50)`) |
| `url` | Must be a valid URL |
| `email` | Must be a valid email address |
| `alpha` | English letters only |
| `alphanumeric` | English letters and digits only |
| `digit` | Digits only |
| `countrycode2` | ISO 3166 Alpha-2 country code |
| `semver` | Semantic versioning format (e.g., `1.2.3`) |
| `regex(pattern)` | Custom regex pattern (e.g., `regex("^[a-z0-9-]+$")`) |

<Aside type="caution">
Regex patterns inside `regex()` must be quoted with double quotes or backticks — e.g., `regex("^[a-z]+$")` or `` regex(`^[a-z]+$`) ``. Additionally, if the overall YAML value contains spaces or special characters, wrap it in quotes at the YAML level too.
</Aside>

### Example with multiple validations

```yaml
- name: SlugName
  type: string
  description: URL-friendly project slug
  validations:
    - required
    - length(3, 30)
    - regex("^[a-z0-9-]+$")
```

## Variable References

For complex types (`list`, `map`), you can reference another variable instead of using Go template interpolation in defaults:

```yaml
variables:
  - name: Services
    type: list
    default:
      - api
      - web

  - name: PrimaryService
    type: string
    reference: Services  # References the Services list
```

## Variable Interpolation

Simple variable defaults can reference other variables using Go template syntax:

```yaml
variables:
  - name: AppName
    default: "my-app"

  - name: ContainerName
    default: "{{ "{{" }} .AppName {{ "}}" }}-container"
```

## Defaults in Interactive Mode

In interactive mode, variables that have a `default` value are **not prompted** — they silently use the default. This matches the behavior of `--non-interactive` mode and avoids issues with defaults that contain Go template expressions (e.g., `{{ "{{" }} .AppName {{ "}}" }}`), which would otherwise be shown as raw template strings in the prompt.

If you want the user to be prompted to confirm or change a default value, set `confirm: true` on the variable:

```yaml
variables:
  - name: AppName
    type: string
    default: "my-app"
    confirm: true  # User will be prompted, with "my-app" as the default

  - name: ContainerName
    type: string
    default: "{{ "{{" }} .AppName {{ "}}" }}-container"
    # No confirm — silently uses the computed default
```

<Aside type="note">
`confirm` only affects interactive mode. In `--non-interactive` mode, defaults are always used without prompting regardless of the `confirm` setting.
</Aside>

## Providing Values

Variables can be provided in multiple ways. When the same variable is set in more than one place, the highest-precedence source wins:

1. `--var` CLI flags (highest)
2. Dependency-level `var_files`
3. `--var-file` CLI files
4. Dependency variable defaults
5. Root variable defaults in `boilerplate.yml`
6. Environment variables (`BOILERPLATE_VAR_<NAME>`)
7. Interactive prompts (lowest)

### `--var` flags

Pass individual values directly on the command line:

```bash
boilerplate \
  --template-url ./my-template \
  --output-folder ./output \
  --var ProjectName="My App" \
  --var Port=8080 \
  --var 'Tags=["web", "api"]'
```

For complex types (lists, maps), use YAML syntax wrapped in quotes.

To set a variable for a specific dependency, prefix it with the dependency name:

```bash
--var 'backend.Port=9090'
```

### `--var-file` files

Load multiple variables at once from a YAML file:

```bash
boilerplate \
  --template-url ./my-template \
  --output-folder ./output \
  --var-file vars/common.yml \
  --var-file vars/production.yml
```

The YAML file is a flat key-value map:

```yaml
# vars/production.yml
ProjectName: "My App"
Port: 8080
Environment: production
Tags:
  - web
  - api
Config:
  host: "prod.example.com"
  port: "443"
```

You can pass `--var-file` multiple times. Later files override earlier ones, so environment-specific files can override shared defaults.

### Dependency-level `var_files`

Inside `boilerplate.yml`, a dependency can specify its own var files:

```yaml
dependencies:
  - name: backend
    template-url: ../go-service
    output-folder: ./backend
    var_files:
      - ../vars/backend-defaults.yml
```

These take precedence over CLI-level `--var-file` values for that dependency.

### Environment variables

Set variables via environment variables using the `BOILERPLATE_VAR_` prefix:

```bash
export BOILERPLATE_VAR_ProjectName="My App"
export BOILERPLATE_VAR_Port=8080

boilerplate \
  --template-url ./my-template \
  --output-folder ./output \
  --non-interactive
```

<Aside type="note">
Environment variables have lower precedence than `--var`, `--var-file`, and defaults in `boilerplate.yml`. They are most useful as fallbacks in CI/CD environments.
</Aside>

### Interactive prompts

In interactive mode (the default), Boilerplate prompts for any variable that has no default and hasn't been provided by any of the above methods. Variables with a `default` silently use that default unless `confirm: true` is set (see [Defaults in Interactive Mode](#defaults-in-interactive-mode)). In `--non-interactive` mode, a missing variable with no default causes an error.
