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

# Containers & components

> Discord's newer component layout — sections, separators, media galleries and accent bars.

Embeds are fine, but they're rigid. Containers are Discord's newer layout system: a bordered block with a coloured accent bar that you fill with headers, text, images, thumbnails and buttons in whatever order you like.

Anywhere you can write an embed script, you can write a container instead.

```javascript theme={null}
{box: #5cacec}
{box.header: Server Rules}
{box.text: Be decent to each other. That's mostly it.}
{box.separator}
{box.text: Breaking them gets you a warn, then a mute, then a ban.}
{box.button: label: "Full rules" url: "https://example.com" style: "link"}
```

## Opening a container

| Node                    | Aliases              | Notes                                    |
| ----------------------- | -------------------- | ---------------------------------------- |
| `{container}`           | `box`, `cntr`, `ctr` | Opens a container                        |
| `{container: #hex}`     | —                    | Opens one with an accent colour          |
| `{container: dominant}` | —                    | Accent taken from the first image inside |

Everything after it that starts with `container.` (or `box.`, etc.) belongs to that container. Open a second `{box}` to start a new one.

## What goes inside

<AccordionGroup>
  <Accordion title="Text and headers" icon="text-height">
    | Node                | Aliases                              |
    | ------------------- | ------------------------------------ |
    | `{box.header: ...}` | `heading`, `h`, `title`              |
    | `{box.text: ...}`   | `description`, `desc`, `txt`, `body` |

    ```javascript theme={null}
    {box.header: Welcome to {guild.name}}
    {box.text: {user.mention}, you're member **{guild.members}**.}
    ```

    Both support full Discord markdown, including `-# subtext` and `> quotes`.
  </Accordion>

  <Accordion title="Separators" icon="minus">
    ```javascript theme={null}
    {box.separator}
    {box.separator: large}
    ```

    Aliases: `sep`, `divider`, `hr`. Pass `large` (or `lg` / `big`) for more breathing room; anything else gives the small spacing.
  </Accordion>

  <Accordion title="Images and galleries" icon="image">
    ```javascript theme={null}
    {box.image: https://example.com/one.png}
    {box.image: https://example.com/one.png | https://example.com/two.png}
    ```

    Aliases: `img`, `gallery`, `media`, `photo`, `pic`. Multiple URLs separated by `|` become a media gallery — Discord lays them out as a grid.
  </Accordion>

  <Accordion title="Sections and thumbnails" icon="image-portrait">
    A section is text with a thumbnail floated beside it.

    ```javascript theme={null}
    {box.section: text: "Level 12 — 4,200 xp" thumbnail: "{user.avatar}"}
    ```

    Aliases: `sec`, `row`. The text part accepts `text`, `label`, `description`, `desc`, `content` or `body`; the image part accepts `thumbnail`, `thumb`, `image`, `img` or `icon`.

    `{box.thumbnail: <url>}` is the shorthand for a thumbnail with no text next to it.
  </Accordion>

  <Accordion title="Buttons" icon="hand-pointer">
    Identical to [top-level buttons](/scripting/overview#buttons), just scoped inside the container:

    ```javascript theme={null}
    {box.button: label: "Get roles" emoji: "🎭" style: "success" message: "Head to #roles"}
    ```
  </Accordion>

  <Accordion title="Accent colour" icon="palette">
    Set on the opening node, or separately afterwards:

    ```javascript theme={null}
    {box}
    {box.color: #ff5c8a}
    ```

    ```javascript theme={null}
    {box.dominant}
    ```

    `{box.dominant}` pulls the colour from the first Discord-hosted image in the container.
  </Accordion>
</AccordionGroup>

## Container vs embed

Neither is better — they're for different shapes of message.

|          | Embed                                    | Container                                        |
| -------- | ---------------------------------------- | ------------------------------------------------ |
| Layout   | Fixed: title, description, fields, image | Free — items in the order you write them         |
| Images   | One large, one thumbnail                 | Any number, including galleries                  |
| Buttons  | Below the embed                          | Anywhere inside                                  |
| Accent   | Left colour bar                          | Left colour bar                                  |
| Best for | Structured info, field grids             | Announcements, panels, anything with mixed media |

You can use both in one message — a container plus an embed plus plain content all render together.

## A worked example

A welcome message that actually looks designed:

```javascript theme={null}
!welcome add #general {content: {user.mention}}
{box: dominant}
{box.section: text: "## Welcome to {guild.name}
{user.name} — you're our **{guild.members|comma}th** member." thumbnail: "{user.avatar}"}
{box.separator}
{box.text: -# account created <t:{user.created_at}:R>}
{box.button: label: "Read the rules" style: "secondary" message: "Head over to #rules — it takes 30 seconds."}
```

<Tip>
  Build it with `!embed` first so you can see it, tweak it, and only paste it into `!welcome add` once you're happy. `!copyembed` on the result gives you the script back if you lose it.
</Tip>

## Limits

Discord enforces these, not the bot:

* **40** components total per message
* **10** buttons, across a maximum of **5** rows
* **4000** characters across all text in the message
* Media gallery items must be reachable image URLs

Going over any of these means the message won't send. If a script silently fails to appear, this is usually why — trim it down and try again.
