docs/references/data/preference-schema-guide.md
This guide explains how to add new preference keys to Cherry Studio.
All preference keys MUST follow the format: namespace.sub.key_name
Rules:
/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/Semantic Grouping: Group related settings under common namespaces
app.* - Application-level settingschat.* - Chat/message settingsfeature.* - Feature togglesui.* - UI/theme settingsdata.* - Data/backup settingsshortcut.* - Keyboard shortcutsNamespace principles:
Hierarchy: Use dots for hierarchy, underscores for multi-word names
chat.message.font_size (not chat.messageFontSize)feature.quick_assistant.enabled (not feature.quickAssistant.enabled)Boolean Naming: Use positive names with .enabled suffix for toggles
feature.quick_assistant.enabled (not feature.quick_assistant.disabled)app.spell_check.enabled| Valid | Invalid | Reason |
|---|---|---|
app.user.avatar | userAvatar | Missing dot separator |
chat.multi_select_mode | chat.multiSelectMode | camelCase not allowed |
feature.quick_assistant.enabled | Feature.quickAssistant | camelCase not allowed |
Prefer granular, flat preference keys over storing complex objects.
Why:
When to use flat keys:
// Good: Flat keys for independent settings
'chat.code.collapsible': boolean
'chat.code.show_line_numbers': boolean
'chat.code.wrappable': boolean
When to keep as object:
Only use object values when the data is frequently read/written as a whole unit.
// Acceptable: Shortcut config is always read/written together
'shortcut.general.show_main_window': { binding: string[], enabled: boolean }
Rule of thumb: If you find yourself frequently accessing just one property of an object, split it into separate keys.
Each preference should represent one logical setting. Don't combine unrelated settings.
// Good: One setting per key
'chat.message.font_size': number
'chat.message.font_family': string
// Bad: Multiple settings in one key
'chat.message.font': { size: number, family: string }
All preferences MUST have default values in DefaultPreferences.
If your preference uses a custom type (enum, union type, etc.), add it first.
File: src/shared/data/preference/preferenceTypes.ts
// Example: Adding a new enum type
export enum MyFeatureMode {
auto = 'auto',
manual = 'manual',
disabled = 'disabled'
}
File: src/shared/data/preference/preferenceSchemas.ts
Add your key to the PreferenceSchemas interface:
export interface PreferenceSchemas {
default: {
// ...existing keys (alphabetically sorted)...
'feature.my_feature.enabled': boolean
'feature.my_feature.mode': PreferenceTypes.MyFeatureMode
}
}
In the same file, add default value to DefaultPreferences:
export const DefaultPreferences: PreferenceSchemas = {
default: {
// ...existing defaults (alphabetically sorted)...
'feature.my_feature.enabled': true,
'feature.my_feature.mode': PreferenceTypes.MyFeatureMode.auto,
}
}
import { usePreference } from '@data/hooks/usePreference'
const [enabled, setEnabled] = usePreference('feature.my_feature.enabled')
const [mode, setMode] = usePreference('feature.my_feature.mode')
| File | Purpose |
|---|---|
src/shared/data/preference/preferenceSchemas.ts | Schema interface and default values |
src/shared/data/preference/preferenceTypes.ts | Custom type definitions (enums, unions) |
namespace.category.key_name pattern