The settings dialog is the user's control center for account and product preferences. It combines authenticated account controls with public preferences such as theme, language, and legal links.
Settings code lives under src/features/settings. The feature owns the dialog UI, section navigation, profile image upload, notification preferences, account security helpers, and client state for opening the dialog globally.
What It Includes
The visible settings sections are defined in src/features/settings/constants/settings-nav.constants.ts.
| Section | Authentication | Purpose |
|---|---|---|
| Account | Required | Profile details, email verification, email change, passkeys, password state, two factor authentication, and account deactivation. |
| Notifications | Required | Email marketing and personalized email preferences. |
| Appearance | Public | Light, dark, and system theme selection. |
| Language | Public | App language selection. |
| Legal | Public | Links to Terms of Service and Privacy Policy. |
Account and notification sections require a signed in user. Appearance, language, and legal sections can be shown without account data.
Dialog Structure
The main settings dialog lives in src/features/settings/components/settings-dialog/settings-dialog.tsx.
It supports desktop and mobile layouts. On desktop, the section list and active section can appear together. On mobile, the dialog tracks whether the user is viewing the section list or a single section.
The global bridge lives in src/features/settings/components/settings-dialog/settings-dialog-global-bridge.tsx. It listens for global settings actions so other product surfaces can open settings without prop drilling the dialog state through unrelated components.
Dialog open state is stored in src/features/settings/store/settings-dialog.store.ts.
Account Section
The account section lives in src/features/settings/components/settings-account-section/settings-account-section.tsx.
It includes:
- Profile editing through the profile subsection.
- Current email display.
- Email verification and resend support.
- Email change request support.
- Passkey add and remove flows.
- Password set and change flows.
- Two factor authentication setup, verification, backup code download, and disable flow.
- Account deactivation entry point.
Several account operations use server actions because they depend on the current session, Better Auth, or database state:
| File | Purpose |
|---|---|
src/features/settings/actions/get-password-status.action.ts | Checks whether the current user has a password set. |
src/features/settings/actions/get-passkey-status.action.ts | Checks whether the current user has passkeys. |
src/features/settings/actions/remove-passkeys.action.ts | Removes passkeys for the current user. |
src/features/settings/actions/send-email-verification.action.ts | Sends an email verification request. |
src/features/settings/actions/check-change-email-availability.action.ts | Checks whether a requested new email is available. |
Account deactivation uses the auth feature because deactivation changes account lifecycle state. The feedback flow lives under src/features/auth/account-deactivation.
Profile
The profile subsection lives in src/features/settings/components/settings-profile-section/settings-profile-section.tsx.
It lets users edit their display name and upload a profile image. Profile name validation uses src/features/settings/schemas/settings-profile.schema.ts.
Profile images are uploaded through:
POST /api/account/profile-image
GET /api/account/profile-image?pathname=...The upload route accepts image files up to 2MB and stores them in the private Blob store under the current user's profile image path. Read requests are also scoped to the signed in user, so one user cannot read another user's private profile image by guessing a pathname.
Notifications
The notifications section lives in src/features/settings/components/settings-notifications-section/settings-notifications-section.tsx.
It currently stores two preferences on the user record:
notificationsEmailMarketingnotificationsEmailPersonalized
The API route is src/app/api/account/notification-preferences/route.ts.
The client hooks are:
src/features/settings/hooks/use-fetch-notification-preferences.tssrc/features/settings/hooks/use-mutate-notification-preferences.ts
Validation lives in src/features/settings/schemas/notification-preferences.schema.ts, and database access lives in src/features/settings/repositories/account-notification-preferences.repository.ts.
Use this section when adding new user owned notification preferences. Add the database field, schema field, repository selection, API handling, hook usage, and UI control together so the preference is complete end to end.
Appearance
The appearance section lives in src/features/settings/components/settings-appearance-section/settings-appearance-section.tsx.
It uses next-themes through the shared app provider stack. The available choices are light, dark, and system.
Use this section for user facing theme preferences. Keep provider setup in src/providers, and keep the settings control in the settings feature.
Language
The language section lives in src/features/settings/components/settings-language-section/settings-language-section.tsx.
It is the user facing entry point for locale changes. Locale routing and default locale behavior are documented in the Localization section and governed by skills/i18n.md.
Use this section when changing language selection UI. Use the localization feature and route helpers when changing how locale paths, cookies, or messages work.
Legal
The legal section lives under src/features/settings/components/settings-legal-section.
It gives users quick access to Terms of Service and Privacy Policy from inside the settings dialog. Legal page content itself lives in src/i18n/en/legal.json, and legal rendering is documented in Configuration.
Where To Customize
src/features/settings/constants/settings-nav.constants.tsfor adding, removing, or reordering settings sections.src/i18n/en/settings.jsonfor settings copy.src/features/settings/components/settings-dialog/settings-dialog.tsxfor dialog layout behavior.src/features/settings/components/settings-dialog/settings-section-content.tsxfor section rendering.src/features/settings/components/settings-account-section/settings-account-section.tsxfor account and security controls.src/features/settings/components/settings-profile-section/settings-profile-section.tsxfor profile name and avatar behavior.src/features/settings/components/settings-notifications-section/settings-notifications-section.tsxfor notification controls.src/features/settings/components/settings-appearance-section/settings-appearance-section.tsxfor theme controls.src/features/settings/components/settings-language-section/settings-language-section.tsxfor language controls.src/features/settings/components/settings-legal-sectionfor legal links.
When adding a new settings section, define its section id in src/features/settings/types/settings.types.ts, add the navigation item, add localized copy, render the section content, and keep any data fetching behind feature owned hooks or server actions.