<!-- AI agents: this is the Markdown version of a Reception documentation page. Index: /llms.txt -->

# Remote appearance

Publish native chat colors, localized welcome text, and display settings from the Reception dashboard. ReceptionKit combines published settings with your app’s local appearance and keeps the last valid configuration available offline.

## Open the editor

As an organization owner, open **Settings → Apps → your app → Chat appearance → Customize**. Team members with the Agent role cannot change app settings.

Remote appearance configures existing ReceptionKit components. It does not change your app’s [support entry point](/docs/entry-point), upload fonts, replace the chat layout, or run custom code. Set local values in Swift using the [Appearance guide](/docs/appearance).

![Dashboard chat appearance editor with inspector and preview](/docs/images/dashboard-appearance.webp "The actual editor with example app defaults. Its phone is a web preview; verify the published result in your app.")

## Draft, preview, and publish

1. Select **Conversation**, **Welcome**, or **Action cards** above the phone preview to edit messages, welcome elements, or review and offer cards.
2. Click an element in the phone or select it under **Elements**. On smaller screens, use the **Element** menu. Edit its **Properties**.
3. Choose **Language** for the translation to edit. Choose **Light** or **Dark** to inspect device appearance, and **Fit** or **100%** for preview zoom.
4. Choose **Save draft** to store your work without changing customer chats, or **Publish changes** to save and publish the current editor contents together. Publishing does not require saving a draft first.
5. Verify the result in your app after an appearance fetch completes and you open the chat again.

The header distinguishes **Unsaved changes**, **Draft changes**, **Up to date**, and **App defaults**. **Save draft** is enabled when the editor differs from its saved draft; **Publish changes** is enabled when it differs from the published document. There is no automatic saving or publication.

> **Note:** The browser preview is an approximation of the native chat. It cannot read local `Reception.shared.appearance` values, bundled fonts, or your app’s color assets. Its built-in sample copy and translation fallback do not fully reproduce the SDK’s 48-language behavior. Verify localization, Dynamic Type, contrast, and native rendering in your app.

The preview’s device appearance selector does not publish a color-scheme override. If **Appearance** is set to **Always light** or **Always dark**, that explicit setting also takes precedence over the preview’s Light/Dark selection. Language, preview state, and zoom are editor controls, not customer settings.

### Save conflicts

If another owner or browser tab saved first, the dashboard reports that the app changed or is no longer available instead of overwriting newer settings. Your current edits remain in the open editor. Copy any text and color values you want to retain before reloading, then review the latest draft and reapply your changes. Failed saves also retain the current editor contents for retry.

## Available controls

Every remote property is optional. **Use app default** removes a dropdown override. Clear a text or color field to inherit its local value. Explicitly choosing a default-looking value still publishes an override.

To use your app’s own theme or Swift variables, [assign appearance values in Swift](/docs/appearance#app-themes-and-variables) and leave the corresponding dashboard overrides unset. The dashboard accepts explicit color values, not Swift variable names. Existing color overrides can be cleared with **App colors** and then **Publish changes**; after the updated configuration is fetched and activated, those colors inherit your app’s local values again.

### Accent and outgoing bubbles

Select **Outgoing messages** or **Send button**, then edit **Accent & outgoing bubbles**. This corresponds to `Reception.shared.appearance.accentColor`. It colors outgoing bubbles and accented controls, including the enabled send button and cards without their own color override. Without a local or remote override, it uses the app accent color.

### Text on accent

In **Outgoing messages** or **Send button**, **Text on accent** corresponds to `onAccentColor`. It colors text and symbols on accent surfaces. The SDK default is white; check contrast against both accent variants.

### Chat background

Select **Background** to edit **Chat background**. This corresponds to `chatBackground`; the SDK default is the system background.

### Incoming bubbles

Select **Incoming messages** to edit **Incoming bubbles**. This corresponds to `incomingBackground`; the SDK default is the secondary system background.

### Incoming text

In **Incoming messages**, **Incoming text** corresponds to `incomingForeground`. The SDK default is the primary label color.

### Light and dark color values

Each of the five colors has independent **Light** and **Dark** fields. Enter an opaque six-digit hex color such as `#6954C8`. Three-digit hex, alpha values, and color names are not accepted. The color popover offers saturation/brightness, hue, Hex/RGB input, swatches, and **Reset to app default** for the selected color and mode. Arrow keys adjust the saturation/brightness field; Shift increases the step.

Under **Start with a palette**, **Ocean**, **Iris**, **Forest**, and **Graphite** set paired light/dark accent colors and white text on accent. They preserve other settings. **App colors** clears all five remote color overrides while preserving text and behavior settings. These actions modify the draft until published.

### Chat title

Select **Chat title**. This corresponds to `title` and accepts up to 80 characters per translation. Without overrides, the SDK displays localized “Support”.

### Welcome heading

Switch the preview to **Welcome**, then select **Welcome heading**. This corresponds to `welcomeTitle` and accepts up to 160 characters per translation. Its built-in English text is “Questions, feedback, or a bug?”

### Welcome message

In **Welcome**, select **Welcome message**. This corresponds to `welcomeText` and accepts up to 1,000 characters per translation. Its built-in English text is “You're chatting directly with our team.” Welcome text appears in the empty chat, not above an existing conversation.

All three text fields are trimmed when saved. Blank text removes that translation, and placeholder text is not saved unless entered. Choose from the [48 supported languages](/docs/language).

The composer placeholder is a built-in localized SDK string. Selecting **Send button** edits accent colors; there is no custom composer-text option.

### Appearance

Under **Chat settings**, **Appearance** corresponds to `preferredColorScheme`:

| Dashboard choice | Effect |
| --- | --- |
| Use app default | Retain local `preferredColorScheme`. |
| Follow app | Clear a local forced scheme and follow the host app. |
| Always light | Force light appearance for the chat. |
| Always dark | Force dark appearance for the chat. |

### Font style

**Font style** corresponds to `fontDesign` and offers **System**, **Rounded**, **Serif**, and **Monospaced**. **Use app default** retains the local design. System font designs preserve Dynamic Type.

`fontFamily` is local-only. A non-`nil` `Reception.shared.appearance.fontFamily` takes precedence over both local and remote `fontDesign`. Set the local family to `nil` to use dashboard font designs. The dashboard cannot upload, download, or clear a custom font family.

### Close button

**Close button** corresponds to `showsCloseButton`: choose **Show**, **Hide**, or **Use app default** to inherit the local value. The SDK default is `false`. This adds an optional control when the SDK chat is presented as a sheet; it does not add dismissal UI to a chat embedded in your navigation. The sheet’s native drag indicator remains available.

### Close icon

When **Close button → Show** is selected, **Close icon** offers **Cross ×**, **Chevron down ⌄**, and **Arrow down ↓**. These map to local `.xmark`, `.chevronDown`, and `.arrowDown`. **Use app default** retains the local icon; the SDK default is `.xmark`.

The Close button element is selectable only when the draft explicitly shows it. Hiding it removes that selection from the editor without deleting its stored icon setting.

### Older messages

**Older messages** corresponds to `fadesOlderMessages`: choose **Fade bubble color** or **Keep the same color**. **Use app default** inherits the local setting, whose SDK default is `true`. Fading lightens older outgoing text bubble fills toward white. **Increase Contrast** disables this fading even when enabled in appearance settings.

### Team photos and names

As an owner, open **Settings → Apps → your app → Chat appearance**. **Show team photos** and **Show team names** are independent switches, both off by default.

- **Show team photos:** shows the teammate's uploaded profile photo beside the last reply in each group, with an initial when the photo is unavailable.
- **Show team names:** shows the teammate's first name above each group of replies.

Teammates upload their photo in **Settings → Profile**. Only current organization members with a profile name appear.

A switch publishes its setting immediately and updates the saved editor draft. In **Customize → Chat settings**, the same options are **Team photos** and **Team names**; editor changes need **Publish changes**. Reopen chat after the app fetches the update to see it. Use a ReceptionKit version that supports team display.

![Native chat with a teammate's first name above replies and profile photo beside them](/docs/images/ios-team-replies.webp "Team photos and names enabled for an example support conversation.")

### Welcome icon

In the **Welcome** preview, select **Welcome icon**. Choose a symbol or upload a **Custom image**. **Icon color** sets light and dark colors for symbols. The default is the gray two-bubble icon; the browser preview approximates the native symbols.

**Size** (16–160 pt, default 44) and **Horizontal** and **Vertical position** (up to 120 pt either way) apply to both symbols and images. Drag the icon in the preview to move it; **Center** resets the position. Moving the icon never moves the welcome heading or text, and its size scales with Dynamic Type.

### Review and offer cards

In the **Action cards** preview, select **Review card** or **Offer card**. Each has its own:

- **Button icon** and **Trailing icon:** choose a symbol or an image from your asset library. Defaults are a star and arrow up right for reviews, a gift and chevron for offers.
- **Icon size:** 8–28 pt for both icons, default 12, scaled with Dynamic Type.
- **Button color** and **Button text & icons:** light and dark colors. Unset, the button uses the accent colors.

If a symbol is unavailable on the device, the SDK uses the default icon. Set button labels and send cards through [Reviews](/docs/reviews#send-review-card) or [Paywall cards](/docs/paywalls). A card without text shows only its button.

### Custom images

Welcome, card and close icons can use an image from your organization's asset library. **Custom close icon** appears when **Close button → Show** is selected. **Choose** opens the library; **Upload** adds a file to it. Images keep their own colors; color settings apply to symbols. Choose **Remove** to return to the symbol.

**Settings → Assets** holds the library, shared by all your apps and managed by owners:

- Non-animated SVG, PNG, JPEG or WebP, up to 2 MB per file. Reception converts each file to a transparent PNG of at most 512 px, because iOS can't draw SVG from a URL, and never stores the original.
- The library holds 50 MB of converted images. When it's full, uploads stop until you delete files.
- A file used by any app, in its draft or published appearance, shows where it's used and can't be deleted until you replace it there.

### Hide elements

Turn off **Show** for **Chat title**, **Welcome heading**, or **Welcome message**. **Welcome icon** has **Show icon**; cards have **Show button icon** and **Show trailing icon**. Hidden title and welcome elements stay faintly visible in the preview so you can select them again.

### Restore defaults

**Restore default** under **Properties** clears the selected element's overrides, including visibility. For titles and welcome text, it clears every translation. **Outgoing messages** and **Send button** share accent colors, so restoring either resets both. Choose **Publish changes** to apply.

## Precedence and fallback

For each supported property, resolution is **valid active remote value → local `Reception.shared.appearance` value → SDK default**. Remote appearance must be enabled, and a fetched document must be activated before its values participate. The local-only `fontFamily` exception is described above.

Reading `Reception.shared.appearance` returns your local settings, not the merged appearance displayed by the chat. Remote settings never mutate that property. There is no public getter for the merged appearance.

### Per-mode color fallback

A remote light color overrides only the light mode. If its dark value is missing or invalid, dark mode uses the corresponding local color, or the SDK default if none was set. The SDK does not reuse the remote light value for dark mode. A local asset color keeps its own adaptive behavior in any mode that inherits it.

### Per-language text fallback

For each text field, the SDK tries the canonical selected app-language tag, then its supported language match, case-insensitively. The selected language comes from `Reception.shared.languageOverride` when set, otherwise the host app’s iOS-selected localization. See [Language](/docs/language) for all supported identifiers and matching rules.

For example, an app using `de-AT` can use a matching `de-AT` override, then `de`. If neither has valid text, it keeps the local title or localized SDK default. A published English title does not replace missing German text. An unsupported app language has `en` as its supported match and can therefore use an English remote override.

Blank or overlong remote text is skipped. Text fields fall back independently: a published title does not require a published welcome message. Local custom strings remain your app’s responsibility to translate and reassign when its language changes.

Changing `Reception.shared.languageOverride` immediately re-resolves translations in the active remote document and built-in strings. This does not require fetching a new document. The dashboard’s Language menu only chooses what you edit or preview; it never changes a customer’s language.

### Explicit values versus inheritance

**Hide** overrides a local `showsCloseButton = true`. **Follow app** clears a local forced dark or light scheme. **System** overrides a local rounded font design, unless a custom font family is set. To retain a local value, choose **Use app default**, not the option that happens to resemble the SDK default.

## Fetching, activation, and offline use

ReceptionKit refreshes published appearance while your app is active, including before the first send. This does not register a support device. Publishing does not update every device instantly.

Newly fetched settings take effect the next time chat opens. An open chat keeps its current remote appearance, and opening never waits for a download. If the first opening uses defaults, allow the app to synchronize online and reopen.

Local appearance edits, language changes, light/dark changes, and toggling remote appearance can still update visible chat immediately.

The last valid appearance is available offline and survives logout. Without a saved appearance, the SDK uses local settings and built-in defaults. If an appearance update cannot be downloaded, the chat keeps its previous styling.

## Disable or enable remote appearance

`Reception.shared.usesRemoteAppearance` defaults to `true`. Set it on the main actor during app setup to choose local-only behavior. This example belongs in your host app’s Reception setup code, before opening the chat:

```swift
import SwiftUI
import ReceptionKit

@MainActor
func useLocalSupportAppearance() {
    Reception.shared.usesRemoteAppearance = false
    Reception.shared.appearance.accentColor = .indigo
    Reception.shared.appearance.fontDesign = .rounded
}
```

Disabling remote appearance uses local settings and stops automatic appearance updates. It preserves the saved appearance and your dashboard publication.

To enable it again, run this in your app’s main-actor setup or settings action:

```swift
Reception.shared.usesRemoteAppearance = true
```

Enabling it restores the saved remote appearance and automatic updates. Newly fetched settings still take effect on the next opening. There is no public force-refresh method.

## Restore defaults

**Restore defaults** clears the whole editor document. It does not immediately change the saved draft or live appearance. Choose **Save draft** to retain the reset for later, or **Publish changes** to publish the empty document. A published reset follows the same fetch-and-next-opening timing as any other change.

An empty remote document restores your app’s local values, including local custom colors and strings. It restores pure SDK defaults only where the app has no local override. For a smaller reset, clear one text translation or color mode, choose **Use app default** for one behavior, or use **App colors** to remove all color overrides.

The editor keeps the current draft and publication, not a historical revision list. To return to an earlier custom appearance, re-enter those settings and publish them.

## Verify a change and diagnose invisible edits

In a test app, publish a distinctive title for its selected language. Keep the app open and online, then close and reopen chat. Check an empty chat, an existing conversation, and both light and dark modes.

| Symptom | What to check |
| --- | --- |
| Preview changed, app did not | **Save draft** does not publish. Confirm **Publish changes** succeeded for the dashboard app whose App ID is configured in your iOS app. |
| Publication succeeded, open chat is unchanged | Keep the app open and online, then reopen chat. A published change does not replace the appearance of an already open chat. |
| No update after waiting | Confirm remote appearance is enabled and the configured app is active. Offline/background apps cannot fetch. |
| Only one mode changed | Light and dark overrides are independent. Check the other field and any forced Appearance setting. |
| Text changed only in some languages | Select the correct translation. Missing translations inherit locally; the preview’s language is not the device’s language. |
| Welcome text is invisible | Welcome copy is for an empty chat. Inspect **Welcome** in the preview and an unused chat in the app. |
| Font style does not change | A non-`nil` local `fontFamily` wins. Clear it in Swift to use system designs. |
| Close button is missing | Choose **Show** and present the chat as a sheet. Embedded navigation does not gain a close control. |
| Fade is enabled but bubbles do not fade | Check **Increase Contrast** in iOS settings and whether there are newer outgoing text messages. |
| Preview and app differ | The preview cannot read local overrides and approximates fonts, native materials, and localization. Verify in the native app. |
| Reading `Reception.shared.appearance` shows old values | This property intentionally returns local values, not resolved remote settings. |
| Restore defaults kept custom styling | Publish the reset and reopen after fetching. Any local custom styling remains. |
| Draft cannot save or publish | Check six-digit colors, text lengths, owner access, and the inline error. For a version conflict, preserve edits before reloading. |

For general integration and connection problems, see [Troubleshooting](/docs/troubleshooting).
