Element Web Labs Feature Gating#
Labs features in Element Web are experimental capabilities that are off by default and can be toggled by users or operators. The labs.md documentation describes them as "not finalised, they may be fragile, they may change, they may be dropped." A stable labs feature may eventually be promoted to a Beta or shipped unconditionally.
Enabling the Labs UI#
Two config.json fields control labs at the top level:
show_labs_settings— Whentrue, exposes the Labs tab in user settings.showLabsFlags()also returnstruewhen the user has developer mode enabled, bypassing this gate. Defaults tofalse.features— ARecord<string, boolean>map that sets the default value of individual lab features at the config level (e.g.{ "feature_jump_to_date": true }). This is the only way to enable features whosesupportedLevelsisCONFIG-only.
Setting Definition: IFeature#
Every labs feature is a setting definition that satisfies the IFeature interface. Required fields are isFeature: true and labsGroup (a LabGroup enum value such as Messaging, Encryption, or Developer). Optional fields include controller, supportedLevels, supportedLevelsAreOrdered, shouldWarn, and description.
The canonical registry of all settings is apps/web/src/settings/Settings.tsx.
Gating Patterns#
1. User-Toggleable (Default Pattern)#
Most labs features use supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG_PRIORITISED (i.e. [SettingLevel.CONFIG, SettingLevel.DEVICE]) with supportedLevelsAreOrdered: true . This means:
- Operators can force a value in
config.json. - Users can override the value in Labs settings (when the Labs UI is shown).
2. Config-Only#
Features with supportedLevels: [SettingLevel.CONFIG] cannot be toggled in the Labs UI — the only way to enable them is via config.json. The canonical example is feature_login_with_qr:
"feature_login_with_qr": {
supportedLevels: [SettingLevel.CONFIG],
isFeature: true,
labsGroup: LabGroup.Ui,
default: false,
description: _td("labs|config_only"),
}
Its description key "labs|config_only" renders a note to users explaining the restriction . The PR implementing this feature explains the rationale: labs flags are unavailable until after login and are cleared on logout, so QR login — which is used before login — must be configured at the operator level.
3. Server-Capability Gating: ServerSupportUnstableFeatureController#
For features that depend on a homeserver advertising a Matrix spec version or unstable feature flag, ServerSupportUnstableFeatureController is attached as the setting's controller. The controller:
- Queries
MatrixClient.isVersionSupported(stableVersion)first . - If the stable version is not supported, iterates through
unstableFeatureGroups— an array of arrays. Each inner array is a feature group where all features must be present (AND logic); across groups the logic is OR . - If neither check passes, the setting is disabled:
getValueOverride()returns theforcedValue(defaulting tofalse) regardless of what the user set . - The optional
disabledMessageis surfaced viasettingDisabledas a user-facing explanation .
Example — feature_jump_to_date :
controller: new ServerSupportUnstableFeatureController(
"feature_jump_to_date",
defaultWatchManager,
[["org.matrix.msc3030"], ["org.matrix.msc3030.stable"]], // either unstable group satisfies
"v1.6", // stable version checked first
_td("labs|jump_to_date_msc_support"), // shown when disabled
)
Example — sendReadReceipts (non-labs, same pattern) : uses forcedValue: true, so receipts are always sent even when the server lacks MSC2285 — the user can still opt out, but the server gap does not silently disable the setting.
The controller extends MatrixClientBackedController, so it re-runs its checks whenever the active MatrixClient changes .
MSC4108 QR Code Sign-In (feature_login_with_qr)#
The Sign in with QR feature (MSC4108 v2024 edition) is a config-only labs feature — see the definition above. At runtime, the welcome page component additionally performs a live server capability check by calling client.doesServerSupportUnstableFeature("org.matrix.msc4108") before rendering the QR login button. This double-gate (config flag + runtime server check) means:
- Operators must opt-in via
config.json. - The server must also advertise
org.matrix.msc4108in/_matrix/client/versionsunstable features.
This is distinct from the existing "Link new device" flow, which uses the same MSC but a different code path .
Reference#
| File | Role |
|---|---|
apps/web/src/settings/Settings.tsx | Central registry of all settings and features |
src/settings/controllers/ServerSupportUnstableFeatureController.ts | Controller for server-capability-gated settings |
docs/labs.md | User-facing description of all current labs features |
| element-web PR #33184 | Implementation of MSC4108 QR login labs feature |