> ## Documentation Index
> Fetch the complete documentation index at: https://docs.amnify.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Example — Azure Resource Group

This is a complete walkthrough of authoring the simplest possible useful template: a single Azure Resource Group. The files match the shipped [`tpl-azure-resource-group`](https://github.com/Amnify/terraform-template/tree/main/templates/azure/resource-group) verbatim, so you can copy them, change the `id`, and ship.

By the end of this page you will have a working template that:

* Provisions one `azurerm_resource_group`.
* Lets the user name it.
* Lets the user pick from a curated list of Azure regions.
* Surfaces the resource group ID, name, and location as outputs.

***

## 1. Directory Layout

In your template repository:

```
templates/
└── azure/
    └── my-resource-group/
        ├── main.tf
        └── template.json
```

The directory name (`my-resource-group`) is what users will see in the URL slug. Keep it short and snake-case.

***

## 2. `main.tf`

```hcl theme={null}
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.0"
    }
  }
}

provider "azurerm" {
  features {}
  subscription_id = var.subscription_id
}

variable "subscription_id" {
  description = "Azure Subscription ID"
  type        = string
}

variable "resource_group_name" {
  description = "Name of the resource group"
  type        = string
}

variable "location" {
  description = "Azure region for the resource group"
  type        = string
  default     = "West Europe"
}

variable "tags" {
  description = "Tags to apply to the resource group"
  type        = map(string)
  default     = {}
}

resource "azurerm_resource_group" "main" {
  name     = var.resource_group_name
  location = var.location
  tags     = var.tags
}

output "resource_group_id" {
  value = azurerm_resource_group.main.id
}

output "resource_group_name" {
  value = azurerm_resource_group.main.name
}

output "location" {
  value = azurerm_resource_group.main.location
}
```

### What is happening, block by block

* The **`terraform { required_providers }`** block pins the Azure provider to `~> 4.0`. This locks the major version while allowing minor and patch updates.
* The **`provider "azurerm"`** block configures Azure. The `features {}` block is required by the provider (even when empty). `subscription_id` comes from a variable so each deployment can target a different subscription.
* **`variable "subscription_id"`** is auto-injected by Amnify from the project's environment config. It must be declared but does **not** appear in `template.json`.
* **`variable "tags"`** is also auto-injected (project + deployment metadata). Declare it; do not duplicate it in `template.json`.
* **`variable "resource_group_name"`** is the only field the user must fill in.
* **`variable "location"`** is also user-facing, but has a sensible default (`"West Europe"`).
* The **`resource`** block creates the resource group, applying the user's chosen name, location, and Amnify-injected tags.
* The **`output`** blocks expose three values to Amnify after apply. Users see them on the deployment run page.

***

## 3. `template.json`

```json theme={null}
{
  "id": "tpl-azure-my-resource-group",
  "name": "Azure Resource Group",
  "description": "Create an Azure Resource Group to organize and manage related cloud resources.",
  "category": "infrastructure",
  "cloud_provider": "azure",
  "iac_type": "terraform",
  "icon": "FolderOpen",
  "variables": [
    {
      "name": "subscription_id",
      "type": "string",
      "description": "Azure Subscription ID",
      "required": true,
      "sensitive": false
    },
    {
      "name": "resource_group_name",
      "type": "string",
      "description": "Name of the resource group",
      "required": true,
      "sensitive": false
    },
    {
      "name": "location",
      "type": "string",
      "description": "Azure region for the resource group",
      "default": "West Europe",
      "required": true,
      "sensitive": false,
      "options": [
        "West Europe",
        "North Europe",
        "East US",
        "East US 2",
        "West US 2",
        "Southeast Asia",
        "UK South",
        "Central US",
        "Germany West Central"
      ]
    }
  ]
}
```

### What is happening, field by field

* **`id`** — change this from `tpl-azure-my-resource-group` to whatever stable identifier you want. It must be unique within your organization.
* **`name`** — display name on the template card.
* **`description`** — shown beneath the name in the library and on the deployment wizard.
* **`category: "infrastructure"`** — categorizes the template under "Infrastructure" in the library filter.
* **`cloud_provider: "azure"`** — must match the parent directory.
* **`iac_type: "terraform"`** — only supported value today.
* **`icon: "FolderOpen"`** — any [Lucide icon](https://lucide.dev/icons/) name. `FolderOpen` reads well for a "container" resource.
* **`variables`** — three entries:
  * `subscription_id` is exposed as a required field so the user picks the subscription. (Some templates omit this and rely entirely on the project's auto-injection — both patterns work.)
  * `resource_group_name` is a free-text required field.
  * `location` is a required field with a `default` and an `options` array, so it renders as a dropdown of Azure regions.

<Info>
  Notice that `tags` is in `main.tf` but **not** in `template.json`. That is intentional — Amnify auto-injects tags. Adding it to `template.json` would force users to fill it in by hand for every deployment.
</Info>

***

## 4. Validate Locally

```bash theme={null}
cd templates/azure/my-resource-group
terraform init -backend=false
terraform validate
```

Expected output:

```
Success! The configuration is valid.
```

If `validate` fails, the most common causes are:

* A variable name in `template.json` that is missing in `main.tf` (or vice versa).
* A typo in the provider version constraint or resource attribute.
* Missing `features {}` block in the `azurerm` provider.

***

## 5. Publish

```bash theme={null}
git add templates/azure/my-resource-group
git commit -m "Add custom Azure Resource Group template"
git push origin main
```

Then in Amnify:

1. Navigate to **Deploy → Templates**.
2. Click **Sync Templates**.
3. Your new template appears in the library within a few seconds, ready for users to deploy.

***

## What This Template Does Not Cover

This is an intentionally minimal example. To explore the full set of features Amnify supports, work through:

* [Example — AWS VPC](/cspm-deploy/create-custom-templates/example-aws-vpc) — `list(object)`, nested `object`, `min_items`, deeply nested `list(object)`, and option-driven enums.
* [template.json Reference](/cspm-deploy/create-custom-templates/template-json-reference) — `condition`, `resource_type`, `parent_field`.
* [Variable Types & Secrets](/cspm-deploy/create-custom-templates/variable-types-and-secrets) — `sensitive` variables and the encryption flow.
