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

# Assets

> Configuring banners, translations and QR code logo for Remnashop

## Banners

The bot supports custom banners for each page and locale. Supported page names: `menu`, `dashboard`, `subscription`, `promocode`, `referral`, `default`.

Supported formats: `jpg`, `jpeg`, `png`, `gif`, `webp`.

Banners are loaded from two sources with different priority:

1. **Your banners** — `/opt/remnashop/assets/banners/` (highest priority)
2. **Bot built-in banners** — `assets.default/banners/` inside the Docker image (fallback)

To **use your own banner**, place the file in `assets/banners/` — it automatically takes priority over the built-in one. To **use a built-in banner**, simply don't place a file.

### Fallback chain

When loading a banner, the system searches in the following order.

**User volume (`assets/banners/`):**

1. `banners/{user_locale}/{page}` — page-specific banner for the user's locale
2. `banners/{user_locale}/default` — default banner for the user's locale
3. `banners/{default_locale}/{page}` — page-specific banner for the default locale
4. `banners/{default_locale}/default` — default banner for the default locale
5. `banners/default` — global user fallback

**Built-in banners (`assets.default/banners/`, inside the image):**

6. `banners/{user_locale}/{page}` — built-in page-specific banner
7. `banners/default` — built-in global banner (last resort)

### Usage examples

* **One image for everything** — place a single `banners/default.jpg`
* **One image per locale** — place `banners/{locale}/default.jpg` for each locale
* **Per-page images** — place `banners/{locale}/{page}.jpg` for each page and locale

### File structure example

```
banners/
├── default.jpg             ← global fallback for all pages and locales
├── ru/
│   ├── default.jpg         ← default for all pages in ru locale
│   ├── menu.jpg
│   └── subscription.jpg
└── en/
    ├── default.jpg
    └── menu.jpg
```

<Note>
  If you don't place any banner, the bot uses its built-in banners from the image. Your own `banners/default.jpg` sets the global fallback for all pages and locales.
</Note>

***

## Translations

Translations are loaded from two sources with different priority:

1. **Your overrides** — `/opt/remnashop/assets/translations/{locale}/custom.ftl` (highest priority)
2. **Bot built-ins** — `assets.default/translations/{locale}/*.ftl` inside the Docker image (fallback for all other keys)

This means:

* New keys added in a bot update are available automatically — no action needed.
* Your overrides in `custom.ftl` are never touched by updates.
* To override any built-in key, add it to `custom.ftl` with your translation.

<Note>
  The built-in files (`buttons.ftl`, `messages.ftl`, `notifications.ftl`, `events.ftl`, `utils.ftl`) live inside the image and always match the bot version. You don't need to edit them in the user volume — `custom.ftl` is enough.
</Note>

### The `custom.ftl` file

Each locale folder may contain a `custom.ftl` file (e.g. `translations/ru/custom.ftl`). It is used both to **override** built-in keys and for your **own** strings — plan names, extra menu buttons, etc.

Add key-value pairs using the Fluent syntax:

```ftl theme={"dark"}
# Override a built-in key
btn-menu-connect = 🚀 Connect

# Your own menu buttons
custom-menu-link1 = 1️⃣ First button
custom-menu-link2 = 2️⃣ Second button

# Your own plan names
custom-plan-name1 = 1️⃣ Basic plan
custom-plan-name2 = 2️⃣ Premium plan
```

To avoid collisions with built-in keys, prefix your own keys with `custom-`.

| Context  | Max length      |
| -------- | --------------- |
| Buttons  | 32 characters   |
| Messages | 1024 characters |

After making changes, restart the container for them to take effect.

<CodeGroup>
  ```bash Restart the container theme={"dark"}
  cd /opt/remnashop && docker compose down && docker compose up -d
  ```
</CodeGroup>

<Warning>
  When you override a built-in key in `custom.ftl`, you also lock in its variables (placeholders). If that key changes in a bot update — a variable is added, renamed, or removed — your translation will no longer match the current key, and rendering the message may fail.

  For this reason, after every update check whether translations changed and, if needed, bring your overrides in `custom.ftl` in line with the current keys. Each release indicates whether translations were affected.

  You can compare translations between versions in the [translations folder history on GitHub](https://github.com/snoups/remnashop/commits/main/assets/translations) or by comparing tags, for example [`v0.7.5...v0.8.0`](https://github.com/snoups/remnashop/compare/v0.7.5...v0.8.0).
</Warning>

***

## QR Code Logo

You can add a custom logo to the center of generated invite QR codes.

* **Path:** `assets/logo.png`
* **Format:** PNG, preferably with a transparent background

If the file exists, it will automatically be overlaid in the center of every generated QR code.
