> For the complete documentation index, see [llms.txt](https://striga.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://striga.gitbook.io/docs/striga-core/settings-hub-and-theme.md).

# Settings Hub & Theme

Register player settings with Striga Core and follow the suite theme. For developers.

Two client-side systems in striga-core link the Striga scripts together:

* **Settings hub**: a script describes its player settings with a schema. A settings UI (the Tokyo HUD `/hud` menu) lists every registered script and edits it through core.
* **Theme bus**: one script (Tokyo HUD) publishes the theme color. The others follow it.

```mermaid
flowchart LR
    S[Your script] -- RegisterSettings --> C[striga-core]
    H[Tokyo HUD /hud] -- GetSettingsProviders / SetProviderSettings --> C
    C -- set / reset / preview --> S
    C -- striga-core:client:settingsChanged --> H
    H -- SetTheme --> C
    C -- striga-core:client:theme --> S
```

***

## RegisterSettings

```lua
local ok, idOrErr = exports['striga-core']:RegisterSettings(schema, handlers)
```

Client only. Returns `true, id` or `false, reason` (the reason is also printed in the console).

```lua
exports['striga-core']:RegisterSettings({
    id = 'my-script',          -- default: your resource name
    label = 'My Script',
    icon = 'gear',             -- phosphor icon name
    order = 50,                -- list order, default 100
    locked = false,            -- true = shown read only, set / reset refused
    fields = {
        { key = 'position', type = 'position', label = 'Position', positions = { 'top-right', 'bottom-right' } },
        { key = 'size', type = 'slider', label = 'Size', min = 0.5, max = 1.5, step = 0.05 },
        { key = 'sound', type = 'switch', label = 'Sound' },
        { key = 'accentMode', type = 'segmented', label = 'Color', options = {
            { value = 'theme', label = 'HUD theme' }, { value = 'custom', label = 'Custom' },
        } },
        { key = 'accent', type = 'color', label = 'Accent', when = { key = 'accentMode', value = 'custom' } },
    },
}, {
    get = function() return mySettings end,                    -- required: current values
    set = function(patch) applyAndSave(patch) return true end, -- required: return true when applied
    preview = function(on) end,                                -- optional: show samples while the UI is open
    reset = function() end,                                    -- optional: back to defaults
})
```

### Schema

| Key      | Type    | Rules                                                                                                |
| -------- | ------- | ---------------------------------------------------------------------------------------------------- |
| `id`     | string  | 1 to 64 chars: letters, digits, `_ - .`. Default: your resource name. One id belongs to one resource |
| `label`  | string  | Max 64 chars. Default: `id`                                                                          |
| `icon`   | string  | Phosphor icon name. Default `gear`                                                                   |
| `order`  | number  | Sort order in the UI. Default `100`                                                                  |
| `locked` | boolean | `true` = read only                                                                                   |
| `fields` | list    | Max 32 fields, keys must be unique                                                                   |

Max 64 providers in total.

### Field types

| Type        | Extra keys                                 | Valid value                                                           |
| ----------- | ------------------------------------------ | --------------------------------------------------------------------- |
| `switch`    | -                                          | `true` / `false`                                                      |
| `slider`    | `min`, `max`, `step` (default 1)           | Number from `min` to `max`                                            |
| `segmented` | `options = { { value, label } }` (1 to 32) | One of the option values                                              |
| `select`    | `options = { { value, label } }` (1 to 32) | One of the option values                                              |
| `color`     | -                                          | `'#rrggbb'` or `'#rrggbbaa'`                                          |
| `position`  | `positions` (optional, 1 to 32 names)      | One of `positions`; without the list, any name or `{ x, y }` (0 to 1) |

Every field has `key` (1 to 32 chars: letters, digits, `_ - .`), `type` and `label` (max 64 chars). Option values are strings (max 64), booleans or numbers.

### `when`: show a field only sometimes

```lua
when = { key = 'accentMode', value = 'custom' }           -- one value
when = { key = 'style', values = { 'card', 'tinted' } }   -- 1 to 8 values
```

The UI shows the field only while the other field has that value. `when.key` must be another field of the same provider. It is a UI hint only: core does not enforce it on `set`.

### Handlers

| Handler       | Required | Called when                                                                   |
| ------------- | -------- | ----------------------------------------------------------------------------- |
| `get()`       | yes      | Core needs your current values. Return a table `{ [key] = value }`            |
| `set(patch)`  | yes      | The UI changed values. `patch` is already checked. Return `true` when applied |
| `preview(on)` | no       | The settings UI opens (`true`) or closes (`false`). Show samples              |
| `reset()`     | no       | The player pressed reset. The UI only shows a reset button when you have it   |

{% hint style="info" %}

* Core checks every key and value in a patch. **One bad value refuses the whole patch** and `set` is not called.
* A `locked` provider refuses `set` and `reset`.
* Errors in your handlers are logged once; core does not crash.
* When your resource stops, its settings are removed (`settingsChanged` with `values = nil`).
  {% endhint %}

### Keep the hub in sync

When your **own panel** changes values, tell core so the hub refreshes:

```lua
exports['striga-core']:NotifySettingsChanged()        -- all your providers
exports['striga-core']:NotifySettingsChanged('my-id') -- one provider
```

### Hub exports (for settings UIs)

| Export                           | Returns / does                                                                                                   |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `GetSettingsProviders()`         | List of `{ id, owner, label, icon, order, locked, fields, reset, preview, values }`, sorted by `order` then `id` |
| `SetProviderSettings(id, patch)` | `true` when applied                                                                                              |
| `PreviewProvider(id, on)`        | `false` when the provider has no `preview`                                                                       |
| `ResetProvider(id)`              | `false` when locked or no `reset`                                                                                |
| `UnregisterSettings(id?)`        | Remove your providers (or one)                                                                                   |

Event: `striga-core:client:settingsChanged` with `id, values` (`values = nil` when removed).

***

## Theme bus

One resource publishes the suite theme. In the Striga suite that is **Striga Tokyo HUD** (`{ accent = '#rrggbb' }`).

```lua
-- read once at start
local theme, publisher = exports['striga-core']:GetTheme() -- theme copy or nil

-- follow changes
AddEventHandler('striga-core:client:theme', function(t)
    theme = t -- nil = no theme, use your own color
end)

-- publish (Tokyo HUD does this)
exports['striga-core']:SetTheme({ accent = '#3b82f6' })
exports['striga-core']:SetTheme(nil) -- clear (publisher only)
```

| Rule       |                                                                                                                              |
| ---------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Shape      | 1 to 32 keys, names like `accent` (letters, digits, `_`), values `'#rrggbb'` or `'#rrggbbaa'`. Anything else returns `false` |
| Publisher  | The last resource that called `SetTheme`. Only it can clear the theme                                                        |
| Stop       | When the publisher stops, the theme is cleared (`striga-core:client:theme` with `nil`)                                       |
| Same value | Publishing the same theme again does not fire the event                                                                      |

{% hint style="success" %}
**Suite pattern:** follow the theme unless the player picked their own color. Striga scripts do this with an `accentMode` field (`theme` / `custom`) and an `accent` color field with `when = { key = 'accentMode', value = 'custom' }`.
{% endhint %}

{% content-ref url="/pages/Xkw616bftBHrHeyFx7fT" %}
[Settings Menu (/hud)](/docs/striga-tokyo-hud/settings-menu.md)
{% endcontent-ref %}

{% content-ref url="/pages/AON7JVqMkR2qjgVuDmUA" %}
[Exports](/docs/striga-core/exports.md)
{% endcontent-ref %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://striga.gitbook.io/docs/striga-core/settings-hub-and-theme.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
