Conditionals & Loops

Structure Creator supports conditionals and loops for creating dynamic structures based on user input.

Conditionals

If Statements

Include content conditionally based on a variable:

<if var="INCLUDE_TESTS">
  <folder name="tests">
    <file name="index.test.ts" />
  </folder>
</if>

The content inside <if> is only created when the variable is truthy.

Truthy Values

A variable is truthy when:

  • Non-empty string
  • "true", "yes", "1", "on" (case-insensitive)

A variable is falsy when:

  • Empty or not set
  • "false", "no", "0", "off" (case-insensitive)

If-Else

Add an alternative with <else>:

<if var="USE_TYPESCRIPT">
  <file name="index.ts" />
</if>
<else>
  <file name="index.js" />
</else>

Important: The <else> must immediately follow the closing </if> tag.

Nested Conditionals

Conditionals can be nested:

<if var="INCLUDE_SRC">
  <folder name="src">
    <if var="USE_TYPESCRIPT">
      <file name="index.ts" />
    </if>
    <else>
      <file name="index.js" />
    </else>
  </folder>
</if>

Loops

Repeat Element

Create repeated content with <repeat>:

<repeat count="3" as="i">
  <file name="file-%i%.txt" />
</repeat>

Creates:

file-0.txt
file-1.txt
file-2.txt

Loop Attributes

AttributeRequiredDescription
countYesNumber of iterations (literal or variable)
asNoLoop variable name (default: "i")

Zero vs One-Indexed

The loop variable is 0-indexed by default. Use _1 suffix for 1-indexed:

<repeat count="3" as="n">
  <folder name="chapter-%n_1%">
    <file name="content.md" />
  </folder>
</repeat>

Creates:

chapter-1/content.md
chapter-2/content.md
chapter-3/content.md

Dynamic Count

Use a variable for the count:

<repeat count="%NUM_MODULES%" as="i">
  <folder name="module-%i_1%">
    <file name="index.ts" />
  </folder>
</repeat>

Nested Loops

Loops can be nested with different variable names:

<repeat count="2" as="row">
  <folder name="row-%row_1%">
    <repeat count="3" as="col">
      <file name="cell-%col_1%.txt" />
    </repeat>
  </folder>
</repeat>

Creates:

row-1/
  cell-1.txt
  cell-2.txt
  cell-3.txt
row-2/
  cell-1.txt
  cell-2.txt
  cell-3.txt

Combining Conditionals and Loops

Use conditionals inside loops:

<repeat count="%NUM_COMPONENTS%" as="i">
  <folder name="Component%i_1%">
    <file name="index.tsx" />
    <if var="INCLUDE_STYLES">
      <file name="styles.css" />
    </if>
    <if var="INCLUDE_TESTS">
      <file name="index.test.tsx" />
    </if>
  </folder>
</repeat>

Examples

Module Structure

<folder name="%PROJECT_NAME%">
  <folder name="src">
    <repeat count="%NUM_MODULES%" as="m">
      <folder name="%MODULE_PREFIX%-%m_1%">
        <file name="index.ts" />
        <if var="INCLUDE_TYPES">
          <file name="types.ts" />
        </if>
      </folder>
    </repeat>
  </folder>
</folder>

Feature Flags

<folder name="src">
  <if var="INCLUDE_AUTH">
    <folder name="auth">
      <file name="login.tsx" />
      <file name="logout.tsx" />
    </folder>
  </if>
  <if var="INCLUDE_DASHBOARD">
    <folder name="dashboard">
      <file name="index.tsx" />
    </folder>
  </if>
</folder>

File Content Templating

The conditionals and loops above control which files and folders are created. But what about dynamic content inside files? For that, Structure Creator provides file content templating.

Enabling Templates

To use template directives inside a file's content, add template="true" to the file element:

<file name="README.md" template="true">
{{if INCLUDE_BADGES}}
![Build](https://img.shields.io/badge/build-passing-green)
{{endif}}

# %PROJECT_NAME%

Welcome to the project!
</file>

Without template="true", the {{if}} syntax is treated as literal text. This opt-in approach ensures compatibility with Handlebars, Mustache, and other templating languages that use double curly braces.

If Conditionals

Include content conditionally based on a variable:

<file name="config.json" template="true"><![CDATA[
{
  "name": "%PROJECT_NAME%",
{{if ENABLE_LOGGING}}
  "logging": true,
{{endif}}
  "version": "1.0.0"
}
]]></file>

If-Else

Add an alternative with {{else}}:

<file name=".env" template="true">
{{if USE_PRODUCTION}}
API_URL=https://api.example.com
{{else}}
API_URL=http://localhost:3000
{{endif}}
</file>

For Loops

Iterate over comma-separated values with {{for item in VAR}}:

<file name="exports.ts" template="true">
{{for module in MODULES}}
export * from './{{module}}';
{{endfor}}
</file>

If MODULES is set to auth, user, billing, this produces:

export * from './auth';
export * from './user';
export * from './billing';

The loop variable (e.g., {{module}}) is replaced with each value in turn.

Truthiness in Templates

A variable is considered truthy when:

  • It exists and is non-empty
  • It is not "false" or "0" (case-insensitive)

A variable is falsy when:

  • It doesn't exist or is empty
  • Its value is "false" or "0"

Nesting

Template directives can be nested:

<file name="features.md" template="true">
# Features

{{for feature in FEATURES}}
## {{feature}}

{{if INCLUDE_DESCRIPTIONS}}
Description for {{feature}} goes here.
{{endif}}

{{endfor}}
</file>

Handlebars Compatibility

The template="true" attribute is required because many projects use Handlebars ({{variable}}), Mustache, or similar templating systems. Without this opt-in:

<!-- This Handlebars template is preserved as-is -->
<file name="template.hbs">
<h1>{{title}}</h1>
<p>{{description}}</p>
</file>

Only when you explicitly enable templating will Structure Creator process the {{if}}/{{for}} directives.

Content Templating Examples

Dynamic README

<file name="README.md" template="true"><![CDATA[
# %PROJECT_NAME%

{{if INCLUDE_BADGES}}
[![License](https://img.shields.io/badge/license-%LICENSE%-blue.svg)]()
{{endif}}

## Description

%DESCRIPTION%

{{for contributor in CONTRIBUTORS}}
- {{contributor}}
{{endfor}}
]]></file>

Package.json with Optional Dependencies

<file name="package.json" template="true"><![CDATA[
{
  "name": "%PROJECT_NAME:kebab-case%",
  "version": "1.0.0",
  "dependencies": {
{{if USE_REACT}}
    "react": "^18.0.0",
    "react-dom": "^18.0.0",
{{endif}}
{{if USE_TYPESCRIPT}}
    "typescript": "^5.0.0",
{{endif}}
    "lodash": "^4.17.21"
  }
}
]]></file>

Config File with Feature Flags

<file name="config.ts" template="true"><![CDATA[
export const config = {
  appName: '%PROJECT_NAME%',
{{if ENABLE_ANALYTICS}}
  analytics: {
    enabled: true,
    provider: '%ANALYTICS_PROVIDER%',
  },
{{endif}}
{{if ENABLE_AUTH}}
  auth: {
    provider: '%AUTH_PROVIDER%',
{{if USE_SSO}}
    sso: true,
{{endif}}
  },
{{endif}}
};
]]></file>