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

# stack

> The stack block declares cloud resources for a single deployment unit.

The `stack` block is the primary declaration in XCL. It contains resource bindings that become Pulumi resources when compiled.

## Syntax

```xcl theme={"theme":"css-variables"}
stack "name" {
    // resource bindings
}
```

A stack directory may span multiple `.xcl` files. All `stack` blocks across all files in the directory are merged into a single compilation unit. The `name` label is for documentation only — the actual Pulumi project name is taken from the **directory name**.

## Named resource binding

```xcl theme={"theme":"css-variables"}
stack "networking" {
    vpc = aws.ec2.Vpc {
        cidr_block = input.vpc_cidr
        tags = {
            Name = "my-vpc"
        }
    }
}
```

`vpc` is the **binding name** — used throughout the stack to reference this resource's outputs (e.g., `vpc.id`).

The type path `aws.ec2.Vpc` maps directly to the Pulumi provider class. The provider segment (`aws`) determines which `pulumi_aws` package is imported.

## Unnamed (fire-and-forget) resources

A resource without a binding name runs but its outputs cannot be referenced:

```xcl theme={"theme":"css-variables"}
stack "bootstrap" {
    aws.iam.RolePolicy {
        role   = input.role_name
        policy = input.policy_doc
    }
}
```

## For clause — iterating over a collection

```xcl theme={"theme":"css-variables"}
stack "networking" {
    subnets = aws.ec2.Subnet {
        for az in input.azs

        vpc_id            = vpc.id
        availability_zone = az
    }
}
```

The `for` clause creates one resource per element of the collection. Inside the block, `az` (or whichever variable name you choose) refers to the current element. For maps, use the key-value form:

```xcl theme={"theme":"css-variables"}
bucket_policies = aws.s3.BucketPolicy {
    for name, config in input.buckets

    bucket = name
    policy = config.policy
}
```

## Count modifier — creating N identical resources

```xcl theme={"theme":"css-variables"}
stack "networking" {
    subnets = aws.ec2.Subnet * 3 {
        for idx in input.azs

        vpc_id     = vpc.id
        cidr_block = "10.0.0.0/16"
    }
}
```

The `* N` modifier (where N is any expression) is combined with a `for` clause. It specifies how many resources to create.

## When clause — conditional resources

```xcl theme={"theme":"css-variables"}
stack "networking" {
    nat = aws.ec2.NatGateway when input.deploy_nat {
        subnet_id = subnets.id
    }
}
```

The `when` condition must be a **Resolved** value — an input field or a locals value. It cannot reference resource outputs (which are `Pending<T>` and only known after apply).

**Error if you use a resource output:**

```
when condition references "vpc" which is Pending<T> (a resource output) — when conditions must be Resolved<T> (use an input or locals value instead)
```

## Referencing resource outputs

After a resource is declared, its outputs are available as `resourceName.outputName`:

```xcl theme={"theme":"css-variables"}
stack "networking" {
    vpc = aws.ec2.Vpc {
        cidr_block = input.vpc_cidr
    }

    subnet = aws.ec2.Subnet {
        vpc_id = vpc.id  // references the vpc resource's id output
    }
}
```

Resource outputs are **Pending** — they are only resolved after the cloud deployment completes. This means you cannot use them in `when` conditions.

## Referencing for-resource outputs

When a resource is created with a `for` clause, referencing it produces a list:

```xcl theme={"theme":"css-variables"}
output "networking" {
    subnet_ids = subnets.id  // list of all subnet IDs
}
```

In generated Python this becomes a list comprehension: `[r.id for r in subnets]`.

## Cross-stack references

Use `@stackName.outputName` to reference an output from a sibling stack:

```xcl theme={"theme":"css-variables"}
stack "cluster" {
    eks = aws.eks.Cluster {
        vpc_id     = @networking.vpc_id
        subnet_ids = @networking.subnet_ids
    }
}
```

The sibling stack must be in a directory adjacent to the current stack's parent. See [Multi-stack workspaces](/v1/xcl/guides/multi-stack-workspaces) for details.

## Match and ternary in resource properties

**Match expressions and ternary expressions are not allowed directly in resource properties.** Move them to a `locals` block first:

```xcl theme={"theme":"css-variables"}
// Error:
stack "s" {
    bucket = aws.s3.Bucket {
        acl = "public" if input.is_public else "private"  // not allowed here
    }
}

// Correct:
locals "s" {
    bucket_acl = "public" if input.is_public else "private"
}

stack "s" {
    bucket = aws.s3.Bucket {
        acl = locals.bucket_acl
    }
}
```

**Error message:** `conditional (if/else) expressions are not allowed in resource properties — move this expression into a locals block`

## Multiple stack blocks

A stack can be spread across files. All `stack "name" { ... }` blocks in the directory are merged, and resource names must be unique across all files.

**Error for duplicate resource names:** `"vpc" is already defined in stack.xcl:3 - remove one, or rename`
