Skip to main content

What is Settings?

settings is a registry of settings screens. Each entry you register becomes a real route in Discord’s settings navigation, listed in the Unbound section next to the built-in General, Plugins, Design, and Developer pages. It registers screens, not values. storage persists the values those screens read and write.
Most plugins don’t need this module. If a plugin exports getSettingsPanel, its card in the Plugins list already gets a settings button, and Unbound renders the returned node on a screen for you. Use registerSettings when you want a top-level entry of your own in the settings list, separate from your plugin’s card.

Registering a screen

registerSettings adds one or more entries to the registry. Entries are keyed: registering the same key again overwrites the previous entry and logs a warning.
Entries are not cleaned up for you. To avoid leaving a dead route behind when your plugin is disabled:
  1. Call registerSettings in your plugin’s start.
  2. Call removeSettings with the same key in stop.

The entry shape

An entry uses the same shape as a route in Discord’s SETTING_RENDERER_CONFIG.
'route'
required
Always 'route'. Routes are the only kind of entry Unbound registers.
string
required
Unique identifier for the entry. removeSettings deletes entries by this key. Built-ins use screaming snake case (UNBOUND_GENERAL). Namespace your keys so they can’t collide.
() => string
required
Hook that returns the title shown in the list and in the screen header. Because it’s a hook, it can read from i18n or from storage and re-render when either changes.
string | null
required
The key of the parent route, or null for a top-level entry. Built-ins pass null.
SettingsScreen
required
The screen this route renders.
string
The section label the entry is grouped under in the settings overview. Built-ins use 'Unbound'.
() => boolean
Hook that decides whether the entry is shown. The built-in Developer page uses it to appear only while developer mode is on.
boolean
Hides the entry from the settings list but keeps the route navigable. Use it for screens you open from code, not ones the user picks from a list.
ComponentType<any>
Component rendered as the row’s leading icon. Built-ins render Discord’s TableRowIcon with an id resolved through assets.

Conditional and hidden entries

usePredicate is a hook, so it can subscribe to storage and show or hide the entry as settings change. The built-in Developer page uses this to appear only after developer mode is enabled.

Removing and inspecting

sections() returns only entries registered through this API. Unbound’s built-in screens are merged in separately when the navigation config is read, so they aren’t in the result.

Settings vs storage

The two modules do different jobs: A settings screen almost always uses both. settings puts the screen in the list, and storage holds the values its controls read and write. Build the screen itself from components. See creating an addon for where the registration goes in a plugin’s lifecycle. Addon enabled-state is persisted by the managers, not by this module.