> ## 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.

# Core Concepts: How erlc.dev Studio Automations Work

> Understand the key building blocks of erlc.dev Studio: event triggers, action blocks, value blocks, variables, pages, and broadcasts.

Before you start wiring blocks together, it helps to understand the mental model behind Studio. Every automation you build follows the same structure: something happens (an **event**), and Studio works through a sequence of **actions** in response. Along the way, **value blocks** supply dynamic data, **variables** hold state, **pages** let you reuse logic, and **broadcasts** let automations talk to each other. This page explains each of these concepts so you can build with confidence.

## The Big Picture: Automations

An **automation** is a self-contained set of blocks that starts with a single event trigger and ends when the last action block finishes executing. Automations run in the cloud — you don't need to keep anything open on your end. Each time the triggering event fires, Studio runs the automation from top to bottom.

<Note>
  Multiple automations can be active on the same server at the same time. Each one runs independently and in parallel when its event fires.
</Note>

***

## Block Categories

<CardGroup cols={3}>
  <Card title="Events" icon="bolt">
    The trigger block that starts an automation. Every automation must begin with exactly one event block.
  </Card>

  <Card title="Actions" icon="arrow-right">
    Sequential steps that do things — send a message, run a command, set a variable, wait.
  </Card>

  <Card title="Values" icon="circle-dot">
    Blocks that return a piece of data. They plug into inputs on action or other value blocks.
  </Card>

  <Card title="Variables" icon="database">
    Named storage slots. Local variables exist for one run; data variables persist across runs.
  </Card>

  <Card title="Logic" icon="code-branch">
    Conditionals, loops, and comparisons that control the flow of your automation.
  </Card>

  <Card title="Pages" icon="file-code">
    Reusable sub-routines you define once and call from anywhere on the same server.
  </Card>
</CardGroup>

***

## Event Blocks

Every automation starts with an **event block** — the trigger that tells Studio when to run. You can only place one event block per automation stack. When the event fires, Studio executes all connected action blocks in order.

Here are the available event triggers:

| Block Type | When It Fires |
| - | - |
| `erlc_when_event` | An in-game ERLC event occurs (e.g. `player_joined`) |
| `erlc_when_slash_command` | A Discord member uses a slash command |
| `erlc_when_discord_button` | A Discord member clicks a button component |
| `erlc_when_discord_modal` | A Discord member submits a modal form |
| `erlc_when_discord_event` | A Discord server event occurs (e.g. member join) |
| `erlc_when_broadcast` | Another automation sends a broadcast signal |
| `erlc_when_bot_online` | Your Discord bot comes online |
| `erlc_when_server_active` | Your ERLC server becomes active |
| `erlc_when_manual` | Manually triggered from the Studio dashboard |
| `erlc_when_test_run` | Triggered by clicking **Run Test** in the editor only |

<Tip>
  Use `erlc_when_test_run` during development to fire your automation on demand without waiting for a real event. It never executes in production.
</Tip>

The `erlc_when_event` block has an `EVENT_TYPE` field where you select which in-game event to listen for — for example, `player_joined` or `player_left`.

***

## Action Blocks

**Action blocks** are the steps that execute when an automation runs. They connect to each other vertically: the bottom connector of one block links to the top connector of the next via a `next.block` relationship. Studio runs them one at a time, in order, from top to bottom.

Common action blocks include:

* **`erlc_bot_send_message`** — Sends a message to a Discord channel.
* **`erlc_command`** — Runs an in-game ERLC server command.
* **`erlc_log`** — Writes a message to the Studio execution log for debugging.
* **`erlc_set_variable`** — Stores a value in a local variable for the current run.
* **`erlc_wait`** — Pauses execution for a specified number of seconds before continuing.

<Info>
  Action blocks have a notch on the top and a bump on the bottom — these are the **previous** and **next** connection points. Value blocks have only an output plug and no top/bottom connectors; they can only be used as inputs to other blocks.
</Info>

***

## Value Blocks

**Value blocks** return data. They don't execute steps on their own — instead, they plug into the input slots of action blocks or other value blocks to supply dynamic information at runtime.

| Block Type | What It Returns |
| - | - |
| `erlc_event_value` | A field from the current event (e.g. player name, user ID) |
| `erlc_text_value` | A static string you type directly into the block |
| `erlc_number_value` | A static number |
| `erlc_variable_value` | The current value of a named variable |
| `erlc_broadcast_value` | A value passed in from a `erlc_broadcast` call |

For example, to make `erlc_bot_send_message` send a dynamic message, you connect an `erlc_event_value` block (set to `player_name`) into its `MESSAGE` input rather than a static `erlc_text_value`.

***

## Variables

Variables let your automations remember information. Studio has two types:

### Local Variables

Local variables exist only for the duration of a single automation run. They are created with `erlc_set_variable` and read with `erlc_variable_value`. Once the automation finishes, local variable values are discarded.

Use local variables to hold intermediate results — for example, building up a message string across several steps before sending it.

### Data Variables (Persistent)

Data variables are stored in the cloud and survive between runs. They retain their value until you explicitly overwrite them using `erlc_data_variable_set`. Read them back at any time with `erlc_data_variable_get`. You can use them to track things like how many times a player has joined, whether a server cooldown is active, or the last person to run a command.

<Warning>
  Data variables are shared across all automations on the same server. Use clear, unique names to avoid one automation accidentally overwriting a value another automation depends on.
</Warning>

***

## Pages

A **page** is a reusable block of logic — think of it as a named sub-routine. You define a page by placing an `erlc_page_start` block and building its logic below it. You then call that page from any automation on the same server using `erlc_call_page`.

Pages are useful when the same sequence of actions appears in multiple automations. Instead of duplicating the blocks everywhere, you define the logic once in a page and call it wherever you need it.

```
[erlc_page_start: "notify-staff"]
  └── erlc_bot_send_message (to staff channel)
  └── erlc_log ("Notification sent")

[erlc_when_event: player_joined]
  └── erlc_call_page ("notify-staff")

[erlc_when_discord_event: member_joined]
  └── erlc_call_page ("notify-staff")
```

<Note>
  Pages run synchronously — `erlc_call_page` waits for the page to finish before moving on to the next action block in the calling automation.
</Note>

***

## Broadcasts

**Broadcasts** are a way for one automation to signal another automation on the same server. You send a broadcast using the `erlc_broadcast` action block, optionally attaching a value with `erlc_broadcast_value`. Any automation that starts with an `erlc_when_broadcast` trigger listening for that broadcast name will immediately fire.

This is useful for decoupling logic. For example, a slash command automation can broadcast a `"start-patrol"` signal, and a separate automation handles all the patrol-start logic — keeping each automation focused and easier to maintain.

```
[erlc_when_slash_command: /startpatrol]
  └── erlc_broadcast ("start-patrol")

[erlc_when_broadcast: "start-patrol"]
  └── erlc_bot_send_message ("Patrol has started!")
  └── erlc_command (in-game announcement)
```

<Tip>
  Use broadcasts to split complex workflows into smaller, named automations. It makes debugging easier — you can test each segment independently using `erlc_when_test_run`.
</Tip>

***

## The Block Catalog

Studio is a **closed system** — you can only use block types that exist in the official block catalog. The editor enforces this automatically: the palette only shows valid blocks, and connection points only accept compatible block shapes. You cannot invent custom block types or import external block definitions.

This constraint is intentional. It ensures every automation runs reliably in the Studio runtime without unexpected errors from unsupported operations.

<Info>
  If there's a block type you need that doesn't exist yet, you can request it through the erlc.dev feedback portal. New blocks are added to the catalog regularly based on community requests.
</Info>

***

## Putting It All Together

Here's how a complete automation uses all these concepts at once:

1. An `erlc_when_event` block fires when `player_joined` is detected.
2. An `erlc_event_value` block reads the `player_name` from the event.
3. An `erlc_set_variable` block stores the name in a local variable called `joining_player`.
4. An `erlc_bot_send_message` block reads that variable via `erlc_variable_value` and sends a welcome message to Discord.
5. An `erlc_broadcast` block signals a `"player-joined-audit"` broadcast so a separate audit-log automation can also fire.

Each piece has a single responsibility, and they compose cleanly together — that's the Studio way of building.

Ready to apply these concepts? Head to the [Quickstart guide](/quickstart) to build your first automation, or browse the [Blocks Overview](/studio/blocks-overview) to see every available block.


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