# Theme

A Theme defines the **complete visual design** of the Gamopanda end-user widget. It covers everything from brand colours and typography to the exact border radius on cards. You create one Theme per account and it is served to every visitor — authenticated or guest — when the widget loads.

:::tip
The widget ships with sensible defaults for every field, so you can go live with just a `name`, `description`, and your `primaryColor`. Tweak other fields later as your design system evolves.
:::

---

## How it works

1. **Create a theme** — provide a `name` and `description`, then override any colour, typography, or component fields you want.
2. **Widget loads** — when the Gamopanda widget is rendered, it fetches the theme and applies all values as CSS custom properties.
3. **Instant updates** — any `PATCH` to the theme is picked up on the next widget load, with no code deployment required.
4. **Guest accessible** — the theme is publicly readable (`isGuestUserReadAccessible: true`) so the widget renders correctly before a user logs in.

---

## Fields

### Basic information

| Field | Type | Required | Max length | Description |
|---|---|---|---|---|
| `name` | string | ✅ | 256 | Internal name for this theme |
| `description` | string | ✅ | 1 024 | Internal description for this theme |

---

## Branding colours

All colour fields must be in **RGBA format**: `rgba(r, g, b, a)` — e.g. `rgba(124, 58, 237, 1)`.

| Field | Required | Default | Description |
|---|---|---|---|
| `primaryColor` | ✅ | `rgba(124, 58, 237, 1)` | Main brand colour — used for primary buttons, active states, and accents |
| `primaryContrastTextColor` | ✅ | `rgba(255, 255, 255, 1)` | Text colour drawn on top of `primaryColor` backgrounds |
| `secondaryColor` | ✅ | `rgba(26, 28, 30, 1)` | Secondary brand colour — used for secondary buttons and alternative surfaces |
| `secondaryContrastTextColor` | ✅ | `rgba(255, 255, 255, 1)` | Text colour drawn on top of `secondaryColor` backgrounds |
| `primaryTextColor` | ✅ | `rgba(26, 28, 30, 1)` | Default body text colour |
| `secondaryTextColor` | ✅ | `rgba(100, 116, 139, 1)` | Muted / secondary body text colour (subtitles, captions) |
| `backgroundColor` | ✅ | `rgba(255, 255, 255, 1)` | Overall widget background colour |
| `surfaceColor` | ✅ | `rgba(255, 255, 255, 1)` | Surface colour used for elevated layers (sheets, drawers) |

---

## Message & alert colours

| Field | Required | Default | Description |
|---|---|---|---|
| `errorColor` | ✅ | `rgba(239, 68, 68, 1)` | Used for error states, validation messages, and alerts |
| `successColor` | ✅ | `rgba(34, 133, 120, 1)` | Used for success confirmations and positive indicators |
| `warningColor` | ✅ | `rgba(232, 161, 5, 1)` | Used for warning banners and caution states |
| `infoColor` | ✅ | `rgba(58, 112, 226, 1)` | Used for informational messages and tooltips |
| `defaultColor` | ✅ | `rgba(115, 118, 116, 1)` | Neutral / default state colour (e.g. disabled elements) |

---

## Typography

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `fontFamily` | string | ✅ | `Plus Jakarta Sans` | The name of the Google Font to load. Use the exact font name as listed on [fonts.google.com](https://fonts.google.com) — e.g. `"Roboto"`, `"Open Sans"`, `"Inter"`. |

The widget loads the specified font from Google Fonts automatically.

---

## Button component

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `componentButtonBorderRadius` | integer (px) | ✅ | `24` | Border radius of all buttons in the widget. `24` gives a fully pill-shaped button; `4` gives a near-square button. |

---

## Card component

Cards are the containers used to display streaks, challenges, and reward entries in the widget.

### Colours & borders

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `componentCardBackgroundColor` | rgba string | ✅ | `rgba(255, 255, 255, 1)` | Card background fill colour |
| `componentCardBorderColor` | rgba string | ✅ | `rgba(226, 232, 240, 1)` | Card border colour |
| `componentCardBorderWidth` | integer (px) | ✅ | `1` | Card border width |
| `componentCardBorderRadius` | integer (px) | ✅ | `16` | Card corner radius |
| `componentCardBoxShadow` | string | ❌ | *(none)* | CSS `box-shadow` value — e.g. `0 2px 8px rgba(0,0,0,0.08)`. Max 255 chars. |

### Text styles

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `componentCardTitleTextColor` | rgba string | ✅ | `rgba(26, 28, 30, 1)` | Card title text colour |
| `componentCardTitleFontSize` | integer (px) | ✅ | `18` | Card title font size |
| `componentCardSubtitleTextColor` | rgba string | ✅ | `rgba(100, 116, 139, 1)` | Card subtitle text colour |
| `componentCardSubtitleFontSize` | integer (px) | ✅ | `14` | Card subtitle font size |
| `componentCardBodyTextColor` | rgba string | ✅ | `rgba(26, 28, 30, 1)` | Card body text colour |
| `componentCardBodyFontSize` | integer (px) | ✅ | `14` | Card body font size |

---

## Real-world examples

**🛍️ E-commerce — purple brand theme (default palette)**

```json
{
  "name": "Shop Brand Theme",
  "description": "Main brand theme for the loyalty widget",
  "primaryColor": "rgba(124, 58, 237, 1)",
  "primaryContrastTextColor": "rgba(255, 255, 255, 1)",
  "secondaryColor": "rgba(26, 28, 30, 1)",
  "secondaryContrastTextColor": "rgba(255, 255, 255, 1)",
  "primaryTextColor": "rgba(26, 28, 30, 1)",
  "secondaryTextColor": "rgba(100, 116, 139, 1)",
  "backgroundColor": "rgba(255, 255, 255, 1)",
  "surfaceColor": "rgba(255, 255, 255, 1)",
  "errorColor": "rgba(239, 68, 68, 1)",
  "successColor": "rgba(34, 133, 120, 1)",
  "warningColor": "rgba(232, 161, 5, 1)",
  "infoColor": "rgba(58, 112, 226, 1)",
  "defaultColor": "rgba(115, 118, 116, 1)",
  "fontFamily": "Plus Jakarta Sans",
  "componentButtonBorderRadius": 24,
  "componentCardBackgroundColor": "rgba(255, 255, 255, 1)",
  "componentCardBorderColor": "rgba(226, 232, 240, 1)",
  "componentCardBorderWidth": 1,
  "componentCardBorderRadius": 16,
  "componentCardBoxShadow": "0 2px 8px rgba(0, 0, 0, 0.06)",
  "componentCardTitleTextColor": "rgba(26, 28, 30, 1)",
  "componentCardTitleFontSize": 18,
  "componentCardSubtitleTextColor": "rgba(100, 116, 139, 1)",
  "componentCardSubtitleFontSize": 14,
  "componentCardBodyTextColor": "rgba(26, 28, 30, 1)",
  "componentCardBodyFontSize": 14
}
```

---

**☕ Food & Beverage — warm amber brand**

```json
{
  "name": "Café Brand Theme",
  "description": "Warm amber theme for the café loyalty widget",
  "primaryColor": "rgba(217, 119, 6, 1)",
  "primaryContrastTextColor": "rgba(255, 255, 255, 1)",
  "secondaryColor": "rgba(41, 37, 36, 1)",
  "secondaryContrastTextColor": "rgba(255, 255, 255, 1)",
  "primaryTextColor": "rgba(41, 37, 36, 1)",
  "secondaryTextColor": "rgba(120, 113, 108, 1)",
  "backgroundColor": "rgba(255, 251, 235, 1)",
  "surfaceColor": "rgba(255, 255, 255, 1)",
  "fontFamily": "Lato",
  "componentButtonBorderRadius": 8,
  "componentCardBorderRadius": 12,
  "componentCardBoxShadow": "0 1px 4px rgba(0, 0, 0, 0.08)"
}
```

> Only the fields you want to override need to be included — unset fields keep their defaults.

---

## Fetching the theme

**As a guest (no authentication required):**

```http
GET /api/v1.0/schema/theme/record/{id}
```

**As a logged in end user:**

```http
GET /api/v1.0/schema/theme/record/{id}
x-enduser-access-token: <token>
x-account-id: <account-id>
```

---

## Access & permissions

| Caller | Allowed operations | Notes |
|---|---|---|
| Admin | CREATE · GET · LIST · UPDATE · DELETE | Full control over themes |
| End user | GET | Read-only access |
| Guest user | GET | Theme is publicly readable — widget styles load before login |

---

## Related resources

| Resource | Description |
|---|---|
| [Template](/template) | Widget copy and labels that pair with this theme |
| [Floating Widget](/floating_widget) | The embeddable widget that consumes the theme for its visual styling |

---

## API reference

See the [API Reference](/api/theme) for full request/response schemas and interactive examples for:

- `GET /schema/theme/record` — get the theme
- `POST /schema/theme/record` — create a theme
- `PATCH /schema/theme/record/{id}` — update a theme
- `DELETE /schema/theme/record/{id}` — delete a theme
