template.json Reference
This is the complete schema reference for the manifest file Amnify reads alongside your .tf files. Every field documented here is parsed and used by Amnify; nothing here is aspirational.
The schema is enforced server-side at sync time. If a manifest is malformed, the sync rejects the template and reports the error.
Top-Level Fields
| Field | Required | Type | Description |
|---|---|---|---|
id | yes | string | Stable, unique identifier for the template. Used as the database key. Convention: tpl-<provider>-<name> (e.g. tpl-azure-resource-group). |
name | yes | string | Display name shown on the template card and in the deployment wizard. |
description | yes | string | One- or two-sentence summary of what the template provisions. |
category | yes | enum | One of: infrastructure, application, database, combo. Used for filtering in the library. |
cloud_provider | yes | enum | One of: azure, aws, gcp. Must match the parent directory under templates/. |
iac_type | yes | enum | Currently only terraform is supported. |
icon | no | string | Name of any Lucide icon (e.g. Network, Database, Cloud, FolderOpen). |
variables | yes | array | List of variable definitions. See the next section. |
Minimal valid example
{
"id": "tpl-azure-resource-group",
"name": "Azure Resource Group",
"description": "Create an Azure Resource Group.",
"category": "infrastructure",
"cloud_provider": "azure",
"iac_type": "terraform",
"icon": "FolderOpen",
"variables": []
}
Variable Definition
Every entry in the variables array describes one input that will be rendered as a form field in the Amnify UI and written to terraform.tfvars.json at deploy time.
| Field | Required | Type | Description |
|---|---|---|---|
name | yes | string | Variable identifier. Must exactly match a variable block in your .tf files. |
type | yes | string | One of: string, number, bool, object, list(object). See Variable Types & Secrets for details. |
description | no | string | Help text displayed beneath the form field. |
required | yes | bool | If true, the user must provide a value before the deployment can proceed. |
default | no | any | Pre-filled value in the form. Type must match type. |
options | no | string[] | Renders the field as a dropdown. Only valid for string-typed variables. |
sensitive | yes | bool | If true, the value is masked in the UI and encrypted at rest with AES-256-GCM. |
resource_type | no | string | Terraform resource type (e.g. azurerm_resource_group). Renders a cloud resource picker that fetches live resources of that type from the user's cloud account. |
parent_field | no | string | Name of a sibling variable whose value scopes the resource picker (e.g. set to vpc_id on a subnet_id field so the picker only shows subnets inside the chosen VPC). |
condition | no | object | { "field": "<sibling_name>", "equals": <value> }. The field is shown only when the sibling's value matches. |
min_items | no | number | Minimum number of items required for list(object) variables. |
schema | no | array | Nested array of variable definitions. Required for object and list(object) types. |
name
Must match a variable block in your .tf files exactly. This is how user-supplied values are routed to Terraform.
{ "name": "resource_group_name" }
variable "resource_group_name" {
type = string
}
type
Determines how the field is rendered and what shape Terraform expects. Supported values:
string— single-line text input.number— numeric input, parsed as JSON number.bool— toggle.object— group of nested fields described by aschemaarray.list(object)— repeating group of nested fields, with add/remove controls.
required
If true, the deployment wizard blocks progress until the field is populated. If false, the field can be left empty and the variable's default (if set) or Terraform's own default kicks in.
default
Pre-fills the field with this value. Should match the variable's type. For list(object) and object, the default is rarely used — set sub-field defaults inside the nested schema instead.
options
Renders a string field as a dropdown with these choices. Useful for region selectors, sizing tiers, enum-like inputs.
{
"name": "region",
"type": "string",
"required": true,
"default": "eu-west-1",
"options": ["eu-west-1", "eu-central-1", "us-east-1", "us-west-2"]
}
sensitive
When true:
- The form field is rendered as a masked password input.
- The value is encrypted (AES-256-GCM, scoped per organization) before being persisted.
- The plaintext is only decrypted in memory inside the deploy worker, just before being merged into
terraform.tfvars.json.
See Variable Types & Secrets for the full encryption flow.
resource_type
Tells Amnify to render a cloud resource picker instead of a free-text input. Amnify queries the user's connected cloud account for resources of the given Terraform type and displays them in a dropdown. Common values:
azurerm_resource_groupazurerm_virtual_networkaws_vpcaws_subnet
parent_field
Used together with resource_type to scope a resource picker to a parent. Example: a subnet picker that only shows subnets inside the VPC the user selected earlier.
[
{
"name": "vpc_id",
"type": "string",
"required": true,
"resource_type": "aws_vpc"
},
{
"name": "subnet_id",
"type": "string",
"required": true,
"resource_type": "aws_subnet",
"parent_field": "vpc_id"
}
]
condition — Conditional Visibility
Hides a field unless a sibling variable has a specific value. Useful for "advanced" toggles that reveal further fields.
[
{
"name": "enable_versioning",
"type": "bool",
"required": true,
"default": false
},
{
"name": "versioning_retention_days",
"type": "number",
"required": false,
"default": 30,
"condition": { "field": "enable_versioning", "equals": true }
}
]
min_items
For list(object), the minimum number of entries the user must add. Use it for fields where "zero items" is meaningless (e.g. a VPC must have at least one subnet).
{
"name": "subnets",
"type": "list(object)",
"required": true,
"min_items": 1,
"schema": [ /* ... */ ]
}
schema — Nested Variables
For object and list(object) types, schema is an array of variable definitions describing the nested fields. The same fields documented above apply recursively — you can nest objects inside lists inside objects to any depth.
{
"name": "subnets",
"type": "list(object)",
"required": true,
"min_items": 1,
"schema": [
{
"name": "name",
"type": "string",
"required": true,
"sensitive": false
},
{
"name": "cidr",
"type": "string",
"required": true,
"sensitive": false
}
]
}
The matching .tf declaration uses optional(...) for non-required fields:
variable "subnets" {
type = list(object({
name = string
cidr = string
}))
}
Categories
The category field controls which group the template appears in inside the library:
| Value | Use for |
|---|---|
infrastructure | Networks, compute, clusters, storage, identity. |
application | Web services, container apps, serverless functions. |
database | Managed database services. |
combo | Multi-component stacks (e.g. webapp + database + cache). |
Field Limits and Conventions
idshould be stable across versions. Renaming it creates a new template; users will not see the rename automatically.descriptionis rendered as plain text (no Markdown).- Variable
nameshould besnake_caseto match Terraform conventions. optionsare case-sensitive; the user's selection is passed verbatim to Terraform.
Next Steps
- Variable Types & Secrets — deeper dive on each type with
.tf↔ JSON examples. - Example — AWS VPC — a manifest that exercises every advanced field on this page.