Skip to content

Commit 28d4484

Browse files
docs: add desktop Feature Manifest reference, reorganize feature definition (#795)
* docs: add desktop Feature Manifest reference, reorganize feature definition Because * The desktop FeatureManifest.yaml schema had no dedicated reference — only a brief example in feature-api.mdx * The generic feature-definition.md was a thin page that didn't clearly direct users to the right platform-specific docs * Engineers defining new desktop features had to piece together the schema from scattered sources This commit * Creates a comprehensive Desktop Feature Manifest Reference doc covering all feature-level properties (description, owner, hasExposure, isEarlyStartup, allowCoenrollment, applications, schema), all variable properties (type, fallbackPref, setPref, enum), a setPref vs fallbackPref comparison, and real-world examples * Adds the new doc to the sidebar under Desktop (first item) * Slims down the registration section in feature-api.mdx with a cross-link to the full reference * Rewrites feature-definition.md as a clear crossroads page pointing to Desktop manifest reference, FML spec, and Cirrus guide Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: address review feedback on feature manifest reference Because * Reviewer requested wording improvements and additional details This commit * Updates intro paragraph wording per reviewer suggestion * Changes Searchfox URL to firefox-main in feature-api.mdx * Adds moz-src:// as an alternative URI scheme for schema validation * Expands "repo root" to "repository root" * Adds note about floats needing to be strings * Updates json type description to "stringified JSON if connected to a pref" * Removes redundant enum note already covered by the table * Simplifies feature definition intro sentence Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: restore original feature definition intro sentence Because * The "as small as a single function or as complex as a whole page" wording provides helpful context for newcomers This commit * Reverts the intro sentence in feature-definition.md to its original form Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: restore inline YAML comments in feature-api example Because * The inline comments provide helpful context for each property right where developers see them This commit * Restores the original YAML comments in the feature registration example Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: restore original feature definition intro wording Because * The original wording ("experimentation ecosystem", "experiment surfaces") is the established terminology This commit * Restores the intro paragraph in feature-definition.md to its original form Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5a94b8d commit 28d4484

4 files changed

Lines changed: 262 additions & 31 deletions

File tree

docs/platform-guides/desktop/feature-api.mdx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ The Nimbus Feature API will return the correct configuration for a feature given
6767
6868
## Registering a new feature
6969
70-
To register a new feature, you will need to choose an identifier and add it to the manifest in [FeatureManifest.yaml](https://searchfox.org/mozilla-central/source/toolkit/components/nimbus/FeatureManifest.yaml):
71-
After adding the feature a build step is required to update the appropriate header file.
70+
To register a new feature, choose an identifier and add it to [FeatureManifest.yaml](https://searchfox.org/firefox-main/source/toolkit/components/nimbus/FeatureManifest.yaml). After adding the feature, a build step is required to update the generated header file.
7271
7372
```yaml
7473
# In FeatureManifest.yaml
@@ -100,6 +99,8 @@ aboutwelcome:
10099
pref("browser.aboutwelcome.enabled", true);
101100
```
102101

102+
See the [Desktop Feature Manifest Reference](/platform-guides/desktop/feature-manifest) for the complete schema, including all feature and variable properties, `setPref` vs `fallbackPref`, enum constraints, and validation.
103+
103104
## Importing the Feature API
104105

105106
Import the `NimbusFeatures` module:
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
---
2+
id: desktop-feature-manifest
3+
title: Feature Manifest Reference
4+
slug: /platform-guides/desktop/feature-manifest
5+
---
6+
7+
# Desktop Feature Manifest Reference
8+
9+
The desktop Nimbus Feature Manifest ([`FeatureManifest.yaml`](https://searchfox.org/mozilla-central/source/toolkit/components/nimbus/FeatureManifest.yaml)) defines every feature that can be configured by experiments and rollouts in Firefox Desktop. Each feature entry declares what variables it exposes, if those variables connect to Firefox prefs, and whether the feature supports exposure telemetry.
10+
11+
After adding or modifying a feature in the manifest, a build step is required to update the generated header file.
12+
13+
:::tip
14+
This reference covers the **Desktop** manifest format (`FeatureManifest.yaml`). For mobile apps, see the [Feature Manifest Language (FML) specification](/technical-reference/fml/fml-spec).
15+
:::
16+
17+
## Feature properties
18+
19+
Each top-level key in `FeatureManifest.yaml` is a feature ID. The feature definition supports these properties:
20+
21+
| Property | Required | Type | Default | Description |
22+
| :--- | :---: | :--- | :--- | :--- |
23+
| `description` | Yes | string || Human-readable description of the feature |
24+
| `owner` | Yes | string || Email of the team or person responsible |
25+
| `hasExposure` | Yes | boolean || Whether this feature records [exposure events](/data-analysis/jetstream/overview#enrollment-vs-exposure) |
26+
| `exposureDescription` | If `hasExposure: true` | string || Describes when/how the exposure event fires |
27+
| `variables` | Yes | object || Variable definitions (can be `{}` if the feature has no variables) |
28+
| `isEarlyStartup` | No | boolean | `false` | Cache values in Firefox prefs for synchronous access during early startup |
29+
| `allowCoenrollment` | No | boolean | `false` | Allow multiple simultaneous experiment/rollout enrollments for this feature |
30+
| `applications` | No | string[] | `["firefox-desktop"]` | Which Firefox processes can enroll (see [Applications](#applications)) |
31+
| `schema` | No | object || JSON Schema for validation (see [Schema validation](#schema-validation)) |
32+
33+
### Applications
34+
35+
The `applications` array specifies which Firefox processes can use this feature:
36+
37+
- `"firefox-desktop"` — the main browser process (default)
38+
- `"firefox-desktop-background-task"` — the background task runner
39+
40+
```yaml
41+
applications:
42+
- firefox-desktop
43+
- firefox-desktop-background-task
44+
```
45+
46+
If omitted, defaults to `["firefox-desktop"]`.
47+
48+
### Schema validation
49+
50+
The optional `schema` property points to a JSON Schema file that validates the combined feature configuration. It has two fields:
51+
52+
- `uri` — a `resource://` or `moz-src://` URI that Firefox loads at runtime for client-side validation
53+
- `path` — a filesystem path (relative to the repository root) where Experimenter can find the schema
54+
55+
```yaml
56+
schema:
57+
uri: resource://nimbus/schemas/PrefFlipsFeature.schema.json
58+
path: toolkit/components/nimbus/schemas/PrefFlipsFeature.schema.json
59+
```
60+
61+
## Variable properties
62+
63+
Each key under `variables` defines a configurable variable. Variables support these properties:
64+
65+
| Property | Required | Type | Description |
66+
| :--- | :---: | :--- | :--- |
67+
| `description` | Yes | string | Human-readable description of the variable |
68+
| `type` | Yes | string | One of `boolean`, `string`, `int`, `json` |
69+
| `fallbackPref` | No | string | Pref to read the default value from (mutually exclusive with `setPref`) |
70+
| `setPref` | No | string or object | Pref that Nimbus actively sets on enrollment (mutually exclusive with `fallbackPref`) |
71+
| `enum` | No | array | Constrains allowed values (`string` and `int` types only) |
72+
73+
### Variable types
74+
75+
| Type | Values | Supports `enum` | Notes |
76+
| :--- | :--- | :---: | :--- |
77+
| `boolean` | `true` / `false` | No | |
78+
| `string` | Text values | Yes | |
79+
| `int` | Whole numbers | Yes | |
80+
| `json` | Arbitrary JSON objects/arrays | No | Stored as stringified JSON if connected to a pref |
81+
82+
:::note
83+
There is no `float` type. If you need floating-point values, use `string` and parse the value in your code.
84+
:::
85+
86+
### `fallbackPref` vs `setPref`
87+
88+
These are **mutually exclusive** — a variable can use one or the other, not both.
89+
90+
| | `fallbackPref` | `setPref` |
91+
| :--- | :--- | :--- |
92+
| **What it does** | Reads the current pref value as the default when no experiment is active | Nimbus actively **sets** the pref when the user enrolls |
93+
| **On enrollment** | No change to the pref | Pref is set to the experiment branch value |
94+
| **On unenrollment** | No change to the pref | Original pref value is restored |
95+
| **If user changes pref** | No effect on enrollment | Causes automatic unenrollment |
96+
| **Use case** | Feature gates and defaults that already exist as browser prefs | Controlling prefs that other code reads directly |
97+
98+
**`fallbackPref` example:**
99+
```yaml
100+
enabled:
101+
type: boolean
102+
fallbackPref: browser.aboutwelcome.enabled
103+
description: Whether the about:welcome page is enabled
104+
```
105+
106+
**`setPref` example:**
107+
```yaml
108+
enabled:
109+
type: boolean
110+
setPref:
111+
branch: default # or "user"
112+
pref: browser.search.visualSearch.featureGate
113+
description: Feature gate for visual search
114+
```
115+
116+
The `setPref` object format has two fields:
117+
- `branch` — which pref branch to set: `"default"` (resets each startup) or `"user"` (persists to disk)
118+
- `pref` — the pref name
119+
120+
:::note
121+
For a deep dive into pref experiment behavior including unenrollment scenarios, pref branch trade-offs, and conflict handling, see [Pref Experiments](/platform-guides/desktop/pref-experiments).
122+
:::
123+
124+
### `enum` constraints
125+
126+
The `enum` property restricts a `string` or `int` variable to a fixed set of values:
127+
128+
```yaml
129+
rankingMode:
130+
type: string
131+
enum:
132+
- default
133+
- interest
134+
- random
135+
description: The ranking algorithm to use
136+
```
137+
138+
## Examples
139+
140+
### Simple feature with a feature gate
141+
142+
```yaml
143+
search:
144+
description: Search service related features
145+
owner: search-and-suggest-program@mozilla.com
146+
hasExposure: true
147+
exposureDescription: >
148+
Recorded when the visual search context menu item is shown.
149+
variables:
150+
visualSearchEnabled:
151+
type: boolean
152+
setPref:
153+
branch: default
154+
pref: browser.search.visualSearch.featureGate
155+
description: Feature gate for visual search
156+
```
157+
158+
### Feature with multiple variable types
159+
160+
```yaml
161+
urlbar:
162+
description: The Address Bar
163+
owner: search-and-suggest-program@mozilla.com
164+
hasExposure: true
165+
exposureDescription: >
166+
Recorded once per session on first urlbar interaction.
167+
variables:
168+
onboardingTimesToShow:
169+
type: int
170+
fallbackPref: browser.urlbar.quickactions.timesToShowOnboardingLabel
171+
description: Number of times to show the onboarding label
172+
quickSuggestRankingMode:
173+
type: string
174+
fallbackPref: browser.urlbar.quicksuggest.rankingMode
175+
enum:
176+
- default
177+
- interest
178+
- random
179+
description: The ranking mode for QuickSuggest
180+
scoreMap:
181+
type: json
182+
description: JSON object mapping result types to scores
183+
```
184+
185+
### Early startup feature
186+
187+
```yaml
188+
aboutwelcome:
189+
description: The about:welcome page
190+
owner: omc-core@mozilla.com
191+
hasExposure: true
192+
exposureDescription: >
193+
Recorded once per session when about:welcome is shown.
194+
isEarlyStartup: true
195+
variables:
196+
enabled:
197+
type: boolean
198+
fallbackPref: browser.aboutwelcome.enabled
199+
description: Whether the about:welcome page is enabled
200+
screens:
201+
type: json
202+
fallbackPref: browser.aboutwelcome.screens
203+
description: Content to show in the onboarding flow
204+
```
205+
206+
### Co-enrolling feature
207+
208+
```yaml
209+
prefFlips:
210+
description: Flip arbitrary prefs for incident response
211+
owner: beth@mozilla.com
212+
hasExposure: false
213+
allowCoenrollment: true
214+
variables:
215+
prefs:
216+
type: json
217+
description: The prefs to set
218+
schema:
219+
uri: resource://nimbus/schemas/PrefFlipsFeature.schema.json
220+
path: toolkit/components/nimbus/schemas/PrefFlipsFeature.schema.json
221+
```
222+
223+
## Further reading
224+
225+
- [Feature API Reference](/platform-guides/desktop/feature-api) — how to access feature values in code
226+
- [Pref Experiments](/platform-guides/desktop/pref-experiments) — deep dive into `setPref` and `fallbackPref` behavior
227+
- [Co-enrolling Features](/technical-reference/fml/coenrolling-features) — how `allowCoenrollment` works
228+
- [FeatureManifest.yaml on Searchfox](https://searchfox.org/mozilla-central/source/toolkit/components/nimbus/FeatureManifest.yaml) — the live manifest

docs/technical-reference/feature-definition.md

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,33 @@ sidebar_position: 2
66

77
In the experimentation ecosystem, experiment surfaces are described as features. A feature is an area of code instrumented with telemetry and accessible for remote configuration. It can be as small as a single function or as complex as a whole page. Some examples:
88

9-
aboutwelcome: The about:welcome page in Desktop
10-
homescreen: The homescreen page in Fenix
11-
tabTrayFeature: The tab tray in Firefox iOS
12-
13-
14-
Features are defined in a Feature Manifest file for the application, and the client code uses the Nimbus SDK to access variables associated with those features.
15-
16-
After landing a new feature in `mozilla-central` and before doing an Experiment or Rollout using it, it is recommended to go through QA to provide an extra layer of stability and possibly be informed of certain limitations that could exist with the feature. See **To test your feature** for information on how to involve QA.
17-
18-
## To define your feature in the feature manifest file
19-
First, look at what is already defined in the manifest file:
20-
* [Desktop](https://searchfox.org/mozilla-central/source/toolkit/components/nimbus/FeatureManifest.yaml)
21-
* Mobile
22-
* [Fenix (Firefox Android)](https://github.com/mozilla-mobile/firefox-android/blob/main/fenix/app/nimbus.fml.yaml)
23-
* [Focus Android](https://github.com/mozilla-mobile/firefox-android/blob/main/focus-android/app/nimbus.fml.yaml)
24-
* [Firefox iOS](https://github.com/mozilla-mobile/firefox-ios/blob/main/nimbus.fml.yaml)
25-
* [Focus iOS](https://github.com/mozilla-mobile/focus-ios/blob/main/nimbus.fml.yaml)
26-
27-
## To test your feature
28-
Starting with 2023, the Ecosystem QA team has begun to test all the available Desktop Nimbus Features and their configurations. This is done in an attempt to ease testing on future experiments using a feature config (old or new) and to provide a baseline health report for it.
29-
30-
For engineers looking to test a new config:
31-
* See [this document](https://docs.google.com/document/d/1oz1YyaaBI-oHUDsktWA-dLtX7WzhYqs7C121yOPKo2w/edit) for steps on how to file a QA request. When logging the ticket, please use the `Feature-Configuration` label in JIRA to mark it as such. [Example](https://mozilla-hub.atlassian.net/browse/QA-1785)
32-
* If you have documentation regarding the feature’s configuration capabilities, please link it to the QA ticket as this helps with Test Plan and Test Case creation.
33-
* The most commonly QA asked questions for feature configs are:
34-
* What specific functionality is enabled in the browser and how exactly could we see it in action?
35-
* Are there any exposed user preferences in about:preferences when using the feature?
36-
* If the feature has an `exposure` event, when does it trigger?
37-
* Does the feature have specific telemetry events and which telemetry data pipeline are we using? Legacy or Glean?
9+
- `aboutwelcome` — the about:welcome page in Desktop
10+
- `homescreen` — the homescreen page in Fenix
11+
- `tabTrayFeature` — the tab tray in Firefox iOS
12+
13+
Features are defined in a manifest file specific to your platform. The manifest declares what variables the feature exposes, how they connect to preferences, and what telemetry the feature records.
14+
15+
## Define your feature
16+
17+
Choose the guide for your platform:
18+
19+
- **Desktop** — add your feature to [`FeatureManifest.yaml`](https://searchfox.org/mozilla-central/source/toolkit/components/nimbus/FeatureManifest.yaml). See the [Desktop Feature Manifest Reference](/platform-guides/desktop/feature-manifest) for the complete schema.
20+
- **Mobile (Android / iOS)** — add your feature to your app's `.fml.yaml` file. See the [Feature Manifest Language (FML) specification](/technical-reference/fml/fml-spec) for the complete schema.
21+
- [Fenix (Firefox Android)](https://github.com/mozilla-mobile/firefox-android/blob/main/fenix/app/nimbus.fml.yaml)
22+
- [Focus Android](https://github.com/mozilla-mobile/firefox-android/blob/main/focus-android/app/nimbus.fml.yaml)
23+
- [Firefox iOS](https://github.com/mozilla-mobile/firefox-ios/blob/main/nimbus.fml.yaml)
24+
- [Focus iOS](https://github.com/mozilla-mobile/focus-ios/blob/main/nimbus.fml.yaml)
25+
- **Web (Cirrus)** — see the [Cirrus integration guide](/platform-guides/web/integration).
26+
27+
## QA testing your feature
28+
29+
After landing a new feature, it is recommended to go through QA before running experiments or rollouts. This provides an extra layer of stability and can surface limitations early.
30+
31+
- See [this document](https://docs.google.com/document/d/1oz1YyaaBI-oHUDsktWA-dLtX7WzhYqs7C121yOPKo2w/edit) for steps on how to file a QA request. Use the `Feature-Configuration` label in Jira. ([Example](https://mozilla-hub.atlassian.net/browse/QA-1785))
32+
- If you have documentation about the feature's configuration, link it to the QA ticket — this helps with test plan and test case creation.
33+
34+
Common questions QA will ask:
35+
- What specific functionality is enabled and how can we see it in action?
36+
- Are there any exposed user preferences in about:preferences?
37+
- If the feature has an exposure event, when does it trigger?
38+
- Does the feature have specific telemetry events and which pipeline (Legacy or Glean)?

sidebars.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ module.exports = {
8383
type: "category",
8484
label: "Desktop",
8585
items: [
86+
"platform-guides/desktop/desktop-feature-manifest",
8687
"platform-guides/desktop/desktop-feature-api",
8788
"platform-guides/desktop/desktop-pref-experiments",
8889
"platform-guides/desktop/onboarding-feature-desktop",

0 commit comments

Comments
 (0)