User settings
UserSettingsState is an opaque key-value store that survives chart layout
switches and reloads. With persistence enabled, the SDK loads it before chart
readiness and autosaves changes made through the chart API.
interface UserSettingsState {
values: Record<string, unknown>;
metadata?: Record<string, unknown>;
}
Understand what storage does
The storage layer round-trips values and emits user-settings-change. It does
not infer what an arbitrary key means or automatically apply host-owned values
to an order ticket, watchlist, panel, or chart option.
Use an application namespace and connect each host-owned key to its consumer:
const key = 'my-app.orderTicket.defaultQuantity';
chart.setUserSetting(key, 100);
const quantity = chart.getUserSettings().values[key];
if (typeof quantity === 'number') {
orderTicket.setDefaultQuantity(quantity);
}
Built-in SDK subsystems may use their documented settings keys. Do not place host data in an SDK-owned namespace.
Enable the automatic lifecycle
const mounted = sdk.chart.mount({
mount: '#chart',
symbol,
interval: '1D',
datafeed,
storage,
features: {
userSettings: true,
},
});
const widget = await mounted.ready();
const chart = widget.chart();
Before ready(), the controller calls loadUserSettings. A stored
UserSettingsState replaces the current values wholesale. null means no
saved settings, so the current initial values remain.
After readiness, these calls update memory, emit an event, and queue autosave:
chart.setUserSetting('my-app.compactMode', true);
chart.removeUserSetting('my-app.compactMode');
chart.setUserSettings({
values: {
'my-app.compactMode': false,
'my-app.orderTicket.defaultQuantity': 100,
},
});
Autosaves are microtask-coalesced, but separate in-flight writes can overlap. Serialize writes in a custom adapter or define last-write-wins ordering on the backend.
features.userSettings: { enabled: true, persistence: false } keeps the
in-memory getters, setters, and change events, but disables the persistence
surface. It is not a manual-save mode.
Connect persistence
Automatic calls include chart, symbol, and interval context but are not guaranteed to include a user id. Bind authenticated identity in the adapter closure or configure it as an adapter default; never authorize from a browser-supplied context value.
Use the REST chart storage adapter when your backend follows the built-in HTTP contract. Use a custom chart storage adapter for different routes or transports. This page owns the settings lifecycle and key semantics; the backend integration pages own transport, authentication, and response validation.
Observe and delete values
const unsubscribe = chart.on('user-settings-change', (event) => {
applyHostSettings(event.payload.values);
});
await chart.deleteUserSettings({ keys: ['my-app.compactMode'] });
await chart.deleteUserSettings(); // Delete all persisted and in-memory values.
unsubscribe();
Automatic load and save failures are reported as recoverable adapter errors; the chart keeps its current values. Direct persistence calls reject when they fail.
Keep chart layout and hotkey state separate
chart.getState() includes user settings as part of the complete runtime
snapshot. chart.getLayout() excludes them because a chart layout is workspace
state, not durable user preference state.
Keyboard shortcuts use HotkeyStorageAdapter, not ChartStorageAdapter. See
Widget hotkeys.
Verify the lifecycle
- Mount with a saved value and confirm it is available immediately after
ready(). - Change one key and confirm one autosave contains the complete current state.
- Reload with the same authenticated scope and confirm the value returns.
- Delete one key, then all keys, and verify both memory and backend state.
- Mount as another user and workspace; neither may receive the first state.
- Return malformed JSON, deny access, and fail a save; each must remain
distinguishable from
null.
Next steps
- REST chart storage adapter — implement the settings request and response shapes.
- Test chart storage — prove load timing, ordering, and tenant isolation.
- Customization precedence — keep persisted preferences separate from chart configuration precedence.