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

# Pages, Broadcasts, and Flow Control in erlc.dev Studio

> Create reusable pages, send signals between automations with broadcasts, and control execution flow using loops, conditionals, and throttles.

As your automations grow, you'll find yourself repeating the same block logic in multiple places. erlc.dev Studio solves this with **pages** — reusable sub-routines you define once and call anywhere. Alongside pages, **broadcasts** let separate automations communicate with each other by name, and a rich set of **flow control blocks** gives you the loops, conditionals, throttles, and error handling you need to build complex, production-ready logic without clutter.

***

## Pages

A page is a self-contained block stack that lives on its own canvas, separate from your main automation stacks. You call a page from any automation using `erlc_call_page`, and execution returns to the caller once the page finishes. Pages are ideal for logic you reuse in more than one place — moderation checks, message formatters, role verification routines, and similar patterns.

<Steps>
  <Step title="Create a page">
    Open the **Pages** tab in the left panel and click **+ New Page**. Give the page a descriptive name. A new, empty canvas opens.
  </Step>

  <Step title="Add an entry block">
    Drag an `erlc_page_start` block onto the page's canvas. This block marks the beginning of the page's logic. Everything you want the page to do goes beneath it.
  </Step>

  <Step title="Build the page logic">
    Connect action and value blocks beneath `erlc_page_start` just as you would in a regular automation. The page can use local variables, call Discord actions, run game commands, and even call other pages.
  </Step>

  <Step title="Call the page from an automation">
    In any automation, drag an `erlc_call_page` block into your action chain. Use the dropdown on the block to select the page you created. When the automation runs and reaches `erlc_call_page`, it executes the entire page before moving to the next block.
  </Step>
</Steps>

<Note>
  Pages share the same local variable scope as the automation that calls them. A variable set before `erlc_call_page` is readable inside the page, and a variable set inside the page is readable after the call returns.
</Note>

<Tip>
  Name your pages with a verb that describes what they do: `Check_Player_Permissions`, `Send_Warning_DM`, `Format_Join_Embed`. This makes `erlc_call_page` dropdowns easy to navigate at a glance.
</Tip>

***

## Broadcasts

Broadcasts are Studio's inter-automation messaging system. One automation fires a named signal — optionally with a data payload — and any automation whose entry block is `erlc_when_broadcast` and whose name matches the signal immediately begins its run.

<CardGroup cols={2}>
  <Card title="erlc_broadcast" icon="tower-broadcast">
    Fires a named broadcast signal with no payload. Any `erlc_when_broadcast` listening for that exact name begins executing.
  </Card>

  <Card title="erlc_broadcast_value" icon="paper-plane">
    Fires a named broadcast signal and attaches a data payload. The receiving automation can read the payload with `erlc_received_message_value`.
  </Card>

  <Card title="erlc_when_broadcast" icon="satellite-dish">
    Entry block that listens for a named broadcast signal. Set the name field to match the name used in `erlc_broadcast` or `erlc_broadcast_value`.
  </Card>

  <Card title="erlc_received_message_name" icon="tag">
    Value block — returns the name of the broadcast signal that triggered the current `erlc_when_broadcast` run.
  </Card>
</CardGroup>

<CardGroup cols={1}>
  <Card title="erlc_received_message_value" icon="inbox">
    Value block — returns the data payload attached to the broadcast. Use it anywhere you need the data the sender included via `erlc_broadcast_value`.
  </Card>
</CardGroup>

### Broadcast example

Say you have a moderation automation that detects a rule violation. Rather than placing all notification logic in one giant stack, you fire a broadcast and let a dedicated notification automation handle it:

**Sender automation** (triggered by `erlc_when_event`):

```json theme={null}
[
  {
    "type": "erlc_broadcast_value",
    "fields": {
      "NAME": "player_warned"
    },
    "inputs": {
      "VALUE": {
        "block": {
          "type": "erlc_event_value",
          "fields": {
            "KEY": "player_name"
          }
        }
      }
    }
  }
]
```

**Receiver automation** (triggered by `erlc_when_broadcast` with name `player_warned`):

```json theme={null}
[
  {
    "type": "erlc_log",
    "inputs": {
      "VALUE": {
        "block": {
          "type": "erlc_received_message_value"
        }
      }
    }
  }
]
```

When the sender fires, the receiver's log block outputs the warned player's name.

<Warning>
  Broadcast names are case-sensitive. `Player_Warned` and `player_warned` are treated as different signals. Establish a naming convention (e.g. all lowercase with underscores) and use it consistently.
</Warning>

***

## Flow Control Blocks

Flow control blocks let you branch, loop, pause, and manage errors inside your automations. All flow control blocks are action blocks — they sit in the vertical chain and execute in order.

### Conditionals

<AccordionGroup>
  <Accordion title="erlc_if_then">
    Executes its inner block stack only when the condition value evaluates to `true`. If the condition is `false`, the inner stack is skipped and execution continues with the next block after `erlc_if_then`.

    ```json theme={null}
    {
      "type": "erlc_if_then",
      "inputs": {
        "CONDITION": {
          "block": {
            "type": "logic_compare",
            "fields": { "OP": "EQ" },
            "inputs": {
              "A": {
                "block": {
                  "type": "erlc_variable_value",
                  "fields": { "NAME": "warning_count" }
                }
              },
              "B": {
                "block": {
                  "type": "math_number",
                  "fields": { "NUM": 3 }
                }
              }
            }
          }
        },
        "DO": {
          "block": {
            "type": "erlc_log",
            "inputs": {
              "VALUE": {
                "block": {
                  "type": "text",
                  "fields": { "TEXT": "Three warnings reached — escalating." }
                }
              }
            }
          }
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="erlc_if_else">
    Like `erlc_if_then`, but provides a second inner stack — the **else** branch — that executes when the condition is `false`. Use this when you need two distinct code paths.
  </Accordion>
</AccordionGroup>

### Loops

<CardGroup cols={2}>
  <Card title="erlc_while" icon="arrow-rotate-right">
    Repeats its inner stack as long as the condition remains `true`. Evaluates the condition before each iteration — if `false` on the first check, the inner stack never runs.
  </Card>

  <Card title="erlc_repeat" icon="arrows-spin">
    Repeats its inner stack a fixed number of times. Provide the count as a number value.
  </Card>

  <Card title="erlc_repeat_for_seconds" icon="clock">
    Repeats its inner stack as rapidly as possible for a specified number of seconds, then continues.
  </Card>

  <Card title="erlc_repeat_until" icon="flag-checkered">
    Repeats its inner stack until the condition evaluates to `true`. Evaluates after each iteration — the inner stack always runs at least once.
  </Card>

  <Card title="erlc_for_each" icon="list-ol">
    Iterates over every item in a list. Exposes the current item as a named variable for the inner stack to use on each iteration.
  </Card>

  <Card title="erlc_forever" icon="infinity">
    Repeats its inner stack indefinitely. Has no next connector — no blocks can be placed after it in the same stack. Use `erlc_stop_run` or `erlc_break_loop` inside the inner stack to exit.
  </Card>
</CardGroup>

### Loop control

<CardGroup cols={2}>
  <Card title="erlc_break_loop" icon="circle-stop">
    Immediately exits the nearest enclosing loop (`erlc_while`, `erlc_repeat`, `erlc_for_each`, `erlc_forever`, etc.) and continues with whatever comes after the loop block.
  </Card>

  <Card title="erlc_continue_loop" icon="forward-step">
    Skips the remainder of the current loop iteration and jumps back to the top for the next iteration.
  </Card>
</CardGroup>

### Stopping execution

<CardGroup cols={2}>
  <Card title="erlc_stop_run" icon="hand">
    Stops the entire automation run immediately. No further blocks in any stack execute. Use this for hard exits when an unrecoverable condition is detected.
  </Card>

  <Card title="erlc_stop_stack" icon="square-xmark">
    Stops the current block stack only. If this block is inside an `erlc_if_then` inner stack, for example, the outer automation continues after the `erlc_if_then` block.
  </Card>
</CardGroup>

### Timing blocks

<CardGroup cols={2}>
  <Card title="erlc_wait" icon="hourglass-half">
    Pauses execution for a specified number of seconds. The automation resumes automatically from the next block after the wait expires.
  </Card>

  <Card title="erlc_wait_until" icon="hourglass-end">
    Pauses execution and polls the condition repeatedly until it evaluates to `true`, then continues. Useful for waiting on an external state change.
  </Card>
</CardGroup>

<Warning>
  Avoid very long `erlc_wait` durations or `erlc_wait_until` loops with slow-changing conditions inside `erlc_forever` blocks — these can keep an automation alive indefinitely and consume run resources.
</Warning>

### Rate limiting and deduplication

<CardGroup cols={2}>
  <Card title="erlc_throttle" icon="gauge-low">
    Wraps an inner block of code and ensures it can only execute once within a given time window. Subsequent calls within the window are silently skipped. Essential for preventing spam when an event fires rapidly.
  </Card>

  <Card title="erlc_run_once" icon="lock">
    Wraps an inner block of code and executes it only on the first call for a given key. All subsequent calls with the same key are skipped — even across different runs. Use this for one-time setup logic.
  </Card>
</CardGroup>

### Error handling

<AccordionGroup>
  <Accordion title="erlc_try_catch">
    Wraps a block of logic in a try/catch structure. The **try** inner stack executes normally. If any block inside it throws a runtime error, execution immediately jumps to the **catch** inner stack instead. Use `erlc_log` in the catch stack to record what went wrong.

    ```json theme={null}
    {
      "type": "erlc_try_catch",
      "inputs": {
        "TRY": {
          "block": {
            "type": "erlc_log",
            "inputs": {
              "VALUE": {
                "block": {
                  "type": "text",
                  "fields": { "TEXT": "Attempting Discord action..." }
                }
              }
            }
          }
        },
        "CATCH": {
          "block": {
            "type": "erlc_log",
            "inputs": {
              "VALUE": {
                "block": {
                  "type": "text",
                  "fields": { "TEXT": "Action failed — check bot permissions." }
                }
              }
            }
          }
        }
      }
    }
    ```
  </Accordion>
</AccordionGroup>

<Tip>
  Wrap any Discord API action that could fail due to permissions (ban, kick, role assignment) in `erlc_try_catch`. Log the error in the catch block so you can diagnose it without the whole automation silently dying.
</Tip>

***

## Flow control quick reference

| Block | Category | What it does |
| - | - | - |
| `erlc_if_then` | Conditional | Run inner stack if condition is true |
| `erlc_if_else` | Conditional | Branch on true/false condition |
| `erlc_while` | Loop | Repeat while condition true (pre-check) |
| `erlc_repeat` | Loop | Repeat N times |
| `erlc_repeat_for_seconds` | Loop | Repeat for N seconds |
| `erlc_repeat_until` | Loop | Repeat until condition true (post-check) |
| `erlc_for_each` | Loop | Iterate over a list |
| `erlc_forever` | Loop | Loop indefinitely |
| `erlc_break_loop` | Loop control | Exit the nearest loop |
| `erlc_continue_loop` | Loop control | Skip to next iteration |
| `erlc_stop_run` | Exit | Halt entire automation run |
| `erlc_stop_stack` | Exit | Halt current block stack only |
| `erlc_wait` | Timing | Pause for N seconds |
| `erlc_wait_until` | Timing | Pause until condition true |
| `erlc_throttle` | Rate limit | Limit execution frequency |
| `erlc_run_once` | Deduplication | Execute only once per key |
| `erlc_try_catch` | Error handling | Catch and handle runtime errors |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.