This document covers the frontend user interface components and systems for managing application settings and configuration in the memos application. It focuses on the React-based settings panels, their state management using React Query and Context API, and integration with backend gRPC services.
For backend settings storage and workspace management services, see page 4.4. For user authentication flows, see page 3.6.
The settings and configuration UI is organized into distinct sections, each managing different aspects of the application. The system uses React Query for server state management, React Context for global state distribution, and Connect RPC clients for backend communication.
Sources: web/src/components/Settings/PreferencesSection.tsx1-113 web/src/components/Settings/MyAccountSection.tsx1-73 web/src/components/Settings/StorageSection.tsx1-248 web/src/components/Settings/MemberSection.tsx1-202 web/src/components/Settings/SSOSection.tsx1-150
Sources: web/src/components/Settings/PreferencesSection.tsx23-35 web/src/components/Settings/MemberSection.tsx55-68
The settings UI uses a set of composable components for consistent layout and styling.
| Component | Purpose | Key Props |
|---|---|---|
SettingSection | Top-level container with optional title and action buttons | title, actions |
SettingGroup | Groups related settings with optional title and separator | title, showSeparator |
SettingRow | Single setting row with label and control | label, tooltip |
SettingTable | Displays tabular data (users, tokens, webhooks, SSO providers) | columns, data, emptyMessage, getRowKey |
Sources: Inferred from usage in web/src/components/Settings/PreferencesSection.tsx72-109 web/src/components/Settings/MemberSection.tsx96-198 web/src/components/Settings/AccessTokenSection.tsx97-131
The PreferencesSection component manages individual user preferences and personal settings.
| Setting | Component | State Management | Description |
|---|---|---|---|
| Language | LocaleSelect | handleLocaleSelectChange | 30+ supported locales from i18n.ts |
| Theme | ThemeSelect | handleThemeChange | system/default/default-dark/midnight/paper/whitewall |
| Default Memo Visibility | Visibility dropdown | handleDefaultMemoVisibilityChanged | PRIVATE/PROTECTED/PUBLIC |
The component uses the useUpdateUserGeneralSetting mutation hook with optimistic updates:
The pattern applies changes immediately to the UI via helper functions (loadLocale, loadTheme), then persists to the backend with React Query mutation, and finally refetches settings on success.
The system supports 30+ locales defined in web/src/i18n.ts6-40 The LocaleSelect component at web/src/components/LocaleSelect.tsx1-42 displays locale names using getLocaleDisplayName() utility. Supported languages include:
Sources: web/src/components/Settings/PreferencesSection.tsx18-112 web/src/components/LocaleSelect.tsx1-42 web/src/i18n.ts6-40 web/src/types/modules/setting.d.ts1-2
The MyAccountSection component provides account management and personal access token functionality.
The component displays the current user's profile information and provides controls to:
The UpdateAccountDialog at web/src/components/UpdateAccountDialog.tsx1-224 handles profile updates:
| Field | Validation | Notes |
|---|---|---|
avatarUrl | Max 2MB file size, base64 encoded | File input with preview |
username | Required, can be disabled by instance setting | disallowChangeUsername policy |
displayName | Can be disabled by instance setting | disallowChangeNickname policy |
email | Optional | Email format |
description | Optional | Textarea, 2 rows |
The component uses isEqual from lodash to detect changes and only includes modified fields in the updateMask array when calling useUpdateUser mutation.
Sources: web/src/components/Settings/MyAccountSection.tsx1-73 web/src/components/UpdateAccountDialog.tsx1-224 web/src/components/ChangeMemberPasswordDialog.tsx1-115
The AccessTokenSection component (embedded in MyAccountSection) manages API access tokens.
The CreateAccessTokenDialog at web/src/components/CreateAccessTokenDialog.tsx1-184 provides:
| Field | Options | Description |
|---|---|---|
| Description | Required string | Token identifier |
| Expiration | 30 days / 90 days / Never | Token lifetime |
After creation, the token value is displayed once in a Textarea (read-only, 3 rows, monospace font). The user can copy it to clipboard. The dialog shows the token on first display, then closes. The token cannot be retrieved again.
The section uses direct userServiceClient calls:
createPersonalAccessToken() - Creates token, returns token string and personalAccessToken objectlistPersonalAccessTokens() - Fetches all tokens for current user, sorted by createdAt descendingdeletePersonalAccessToken() - Removes token by nameOn successful creation, the token is automatically copied to clipboard and a success toast is displayed.
Sources: web/src/components/Settings/AccessTokenSection.tsx1-153 web/src/components/CreateAccessTokenDialog.tsx1-184
The StorageSection component provides interface for configuring file storage backends. This is an instance-level setting accessible to administrators.
| Field | Applies To | Validation | Description |
|---|---|---|---|
storageType | All | Required | Radio group: DATABASE / LOCAL / S3 |
uploadSizeLimitMb | All | Must be > 0 | BigInt, max file upload size |
filepathTemplate | LOCAL, S3 | Required if not DATABASE | Template like "assets/{timestamp}_{filename}" |
s3Config.accessKeyId | S3 only | Required for S3 | AWS access key |
s3Config.accessKeySecret | S3 only | Required for S3 | AWS secret (password input) |
s3Config.endpoint | S3 only | Required for S3 | S3 endpoint URL |
s3Config.region | S3 only | Required for S3 | AWS region |
s3Config.bucket | S3 only | Required for S3 | S3 bucket name |
s3Config.usePathStyle | S3 only | Optional boolean | Path-style vs virtual-hosted-style URLs |
The component implements validation in allowSaveStorageSetting useMemo at web/src/components/Settings/StorageSection.tsx35-56:
uploadSizeLimitMb > 0filepathTemplate is not emptyisEqual from lodash to detect changes from originalSettingOn save, the component calls updateSetting() from InstanceContext with an InstanceSetting message of type storageSetting, then calls fetchSetting(InstanceSetting_Key.STORAGE) to refresh.
Sources: web/src/components/Settings/StorageSection.tsx1-248
The MemberSection provides user administration capabilities for workspace administrators.
The component uses SettingTable to display users with these columns:
| Column | Display | Details |
|---|---|---|
| Username | user.username | Shows "(Archived)" suffix if state === State.ARCHIVED |
| Role | Localized string | stringifyUserRole(): ADMIN → "Admin", USER → "User" |
| Display Name | user.displayName | Nickname field |
user.email | Email address | |
| Actions | Dropdown menu | Edit / Archive / Restore / Delete (cannot act on self) |
Users can be in one of two states from State enum:
State.NORMAL (0) - Active user, shows "Archive" actionState.ARCHIVED (1) - Archived user, shows "Restore" and "Delete" actionsArchived users are displayed with italic text indicating their status but remain in the list.
Create User (web/src/components/CreateUserDialog.tsx1-151):
userServiceClient.createUser()Edit User:
CreateUserDialog with existing userupdateMask if changed)userServiceClient.updateUser() with FieldMaskArchive User:
user.state = State.ARCHIVEDuserServiceClient.updateUser() with updateMask: ["state"]Restore User:
user.state = State.NORMALDelete User:
deleteUserMutation.mutate(name)useDeleteUser hookSources: web/src/components/Settings/MemberSection.tsx1-202 web/src/components/CreateUserDialog.tsx1-151
The SSOSection manages OAuth2 identity provider configurations for workspace authentication.
The SettingTable displays identity providers with:
The section includes a LearnMore component linking to "https://usememos.com/docs/configuration/authentication".
The dialog at web/src/components/CreateIdentityProviderDialog.tsx1-498 provides a comprehensive OAuth2 configuration interface.
The dialog includes templates for common providers at web/src/components/CreateIdentityProviderDialog.tsx25-122:
| Template | Auth URL | Token URL | User Info URL | Scopes | Field Mapping |
|---|---|---|---|---|---|
| GitHub | github.com/login/oauth/authorize | github.com/login/oauth/access_token | api.github.com/user | ["read:user"] | login, name, email |
| GitLab | gitlab.com/oauth/authorize | gitlab.com/oauth/token | gitlab.com/oauth/userinfo | ["openid"] | name, name, email |
| accounts.google.com/o/oauth2/v2/auth | oauth2.googleapis.com/token | googleapis.com/oauth2/v2/userinfo | [userinfo.email, userinfo.profile] | email, name, email | |
| Custom | Empty | Empty | Empty | [] | Empty fields |
| Field | Required | Description |
|---|---|---|
title | Yes | Provider display name |
identifierFilter | No | Optional filter for user identifiers |
type | Yes | Currently only OAUTH2 supported |
oauth2Config.clientId | Yes | OAuth2 client ID |
oauth2Config.clientSecret | Yes (create only) | OAuth2 client secret |
oauth2Config.authUrl | Yes | Authorization endpoint |
oauth2Config.tokenUrl | Yes | Token exchange endpoint |
oauth2Config.userInfoUrl | Yes | User information endpoint |
oauth2Config.scopes | Yes | Space-separated scope string |
oauth2Config.fieldMapping.identifier | Yes | User identifier field from user info response |
oauth2Config.fieldMapping.displayName | No | Display name field |
oauth2Config.fieldMapping.email | No | Email field |
oauth2Config.fieldMapping.avatarUrl | No | Avatar URL field |
The dialog displays the redirect URL when creating: absolutifyLink("/auth/callback").
The allowConfirmAction() function at web/src/components/CreateIdentityProviderDialog.tsx228-251 validates all required fields before enabling the confirm button. On save:
identityProviderServiceClient.createIdentityProvider()identityProviderServiceClient.updateIdentityProvider() with updateMask: ["title", "identifier_filter", "config"]Sources: web/src/components/Settings/SSOSection.tsx1-150 web/src/components/CreateIdentityProviderDialog.tsx1-498
The WebhookSection component manages user-specific webhook configurations for receiving notifications about memo events.
The SettingTable displays webhooks with:
The dialog at web/src/components/CreateWebhookDialog.tsx1-169 provides a simple form:
| Field | Required | Description |
|---|---|---|
displayName | Yes | Easy-to-remember name for the webhook |
url | Yes | Payload URL for webhook POST requests |
Example placeholder: "https://example.com/api/v1/webhook?source=memos"
All webhook operations use the userServiceClient:
Create Webhook:
createUserWebhook({ parent: user.name, webhook: { displayName, url } })Delete Webhook:
deleteUserWebhook({ name: webhook.name })List Webhooks:
listUserWebhooks({ parent: user.name })The section is embedded in PreferencesSection as a separate group at web/src/components/Settings/PreferencesSection.tsx105-107
Sources: web/src/components/Settings/WebhookSection.tsx1-128 web/src/components/CreateWebhookDialog.tsx1-169 web/src/components/Settings/PreferencesSection.tsx105-107
The settings components integrate with two primary MobX stores:
userStore: Manages user-specific settings including:
updateUserSetting()workspaceStore: Manages workspace-level settings including:
upsertWorkspaceSetting()The system follows a consistent pattern where settings changes trigger store updates, which validate and persist changes through gRPC clients, with responses updating the reactive MobX state that re-renders the UI components.
Sources: web/src/store/user.ts web/src/store/workspace.ts web/src/components/Settings/PreferencesSection.tsx17-33
Refresh this wiki