docs: improve experimentation documentation and messaging - #1388
Conversation
✅ Deploy Preview for openfeature ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Code Review
This pull request introduces comprehensive documentation and landing page updates for OpenFeature's experimentation capabilities. It adds a new dedicated 'Experimentation' concept page detailing the roles of the Tracking API, Hooks, and Targeting Key, along with multi-language code examples and a sequence diagram. Additionally, it updates the tracking documentation with an experimentation-focused example, includes an experimentation summary in the introduction, and adds a 'Built for experimentation' feature section to the landing page. I have no feedback to provide.
Signed-off-by: vanshiz <vanshikabhargava29@gmail.com>
Signed-off-by: vanshiz <vanshikabhargava29@gmail.com>
Signed-off-by: vanshiz <vanshikabhargava29@gmail.com>
Signed-off-by: vanshiz <vanshikabhargava29@gmail.com>
📝 WalkthroughWalkthroughChangesExperimentation support
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
docs/reference/concepts/07-tracking.mdx (1)
113-243: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider linking to the experimentation page instead of duplicating the full A/B testing flow.
This new "Experimentation-Focused Example" section repeats nearly the same evaluate-branch-track flow across four languages that
docs/reference/concepts/08-experimentation.mdx(Steps 1-3) already documents. Thecheckout-experimentflag andcheckout-completedevent are identical, only the tracked value differs (29.99 here vs 49.99 in the new page). Keeping the same full example in two places creates a maintenance burden: an update to one page's SDK call pattern can silently drift from the other page's copy.Consider replacing this section with a shorter pointer to
08-experimentation.mdxfor the full step-by-step walkthrough, keeping this page focused on the standalonetrackcall semantics already covered above.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/reference/concepts/07-tracking.mdx` around lines 113 - 243, Replace the duplicated “Experimentation-Focused Example” section in the tracking concepts document with a concise link or pointer to the experimentation concepts document’s Steps 1–3. Remove the repeated four-language evaluate-branch-track examples while preserving this page’s standalone track call semantics and surrounding content.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/reference/concepts/07-tracking.mdx`:
- Around line 119-242: Add a blank line immediately after each of the four
TabItem opening tags (js, java, csharp, and go) before its fenced code block,
matching the formatting used by the surrounding examples and
08-experimentation.mdx.
In `@docs/reference/concepts/08-experimentation.mdx`:
- Line 42: Update the four step headings in the experimentation documentation to
remove the space before each colon, changing “Step N :” to “Step N:”.
- Around line 23-38: Update the Mermaid sequence diagram’s multi-word
participants, “OpenFeature SDK” and “Flag Provider,” to use declared aliases,
then replace those participant names with the aliases in every message arrow and
the “Note over” clause while preserving the diagram’s flow.
---
Nitpick comments:
In `@docs/reference/concepts/07-tracking.mdx`:
- Around line 113-243: Replace the duplicated “Experimentation-Focused Example”
section in the tracking concepts document with a concise link or pointer to the
experimentation concepts document’s Steps 1–3. Remove the repeated four-language
evaluate-branch-track examples while preserving this page’s standalone track
call semantics and surrounding content.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 5acab4c5-38e4-4aa9-a2d2-b5392697b0ee
📒 Files selected for processing (4)
docs/reference/concepts/07-tracking.mdxdocs/reference/concepts/08-experimentation.mdxdocs/reference/intro.mdxsrc/partials/features-zigzag.tsx
| <Tabs groupId="code"> | ||
| <TabItem value="js" label="TypeScript"> | ||
| ```ts | ||
| import { OpenFeature } from '@openfeature/server-sdk'; | ||
|
|
||
| // Set evaluation context with the user's targeting key. | ||
| // The targeting key is how your provider buckets users into variants consistently. | ||
| OpenFeature.setContext({ | ||
| targetingKey: 'user-123', | ||
| }); | ||
|
|
||
| const client = OpenFeature.getClient(); | ||
|
|
||
| // Evaluate the experiment flag — provider returns true (variant) or false (control) | ||
| const useNewCheckout = await client.getBooleanValue('checkout-experiment', false); | ||
|
|
||
| if (useNewCheckout) { | ||
| // Show the new checkout UI (variant group) | ||
| await showNewCheckout(); | ||
| } else { | ||
| // Show the existing checkout UI (control group) | ||
| await showExistingCheckout(); | ||
| } | ||
|
|
||
| // When the user completes the purchase, emit a tracking event. | ||
| // The provider associates this event with the flag evaluation context automatically. | ||
| client.track('checkout-completed', { value: 49.99, currencyCode: 'USD' }); | ||
| ``` | ||
|
|
||
| </TabItem> | ||
| <TabItem value="java" label="Java"> | ||
| ```java | ||
| import dev.openfeature.sdk.*; | ||
|
|
||
| OpenFeatureAPI api = OpenFeatureAPI.getInstance(); | ||
|
|
||
| // Set evaluation context with the user's targeting key | ||
| Map<String, Value> attrs = new HashMap<>(); | ||
| EvaluationContext ctx = new ImmutableContext("user-123", attrs); | ||
| api.setEvaluationContext(ctx); | ||
|
|
||
| Client client = api.getClient(); | ||
|
|
||
| // Evaluate the experiment flag | ||
| Boolean useNewCheckout = client.getBooleanValue("checkout-experiment", false); | ||
|
|
||
| if (useNewCheckout) { | ||
| showNewCheckout(); | ||
| } else { | ||
| showExistingCheckout(); | ||
| } | ||
|
|
||
| // Track the conversion event — provider links it back to the flag evaluation context | ||
| client.track("checkout-completed", new MutableTrackingEventDetails(49.99).add("currencyCode", "USD")); | ||
| ``` | ||
|
|
||
| </TabItem> | ||
| <TabItem value="csharp" label="C#"> | ||
| ```csharp | ||
| using OpenFeature; | ||
| using OpenFeature.Model; | ||
|
|
||
| // Set evaluation context with the user's targeting key | ||
| EvaluationContextBuilder builder = EvaluationContext.Builder(); | ||
| builder.Set("targetingKey", "user-123"); | ||
| EvaluationContext ctx = builder.Build(); | ||
| Api.Instance.SetContext(ctx); | ||
|
|
||
| var client = Api.Instance.GetClient(); | ||
|
|
||
| // Evaluate the experiment flag — all evaluations are async in .NET SDK, note GetBooleanValueAsync | ||
| var useNewCheckout = await client.GetBooleanValueAsync("checkout-experiment", false); | ||
|
|
||
| if (useNewCheckout) { | ||
| await ShowNewCheckout(); | ||
| } else { | ||
| await ShowExistingCheckout(); | ||
| } | ||
|
|
||
| // Track the conversion event | ||
| client.Track("checkout-completed", trackingEventDetails: new TrackingEventDetailsBuilder() | ||
| .SetValue(49.99).Set("currencyCode", "USD").Build()); | ||
| ``` | ||
|
|
||
| </TabItem> | ||
| <TabItem value="go" label="Go"> | ||
| ```go | ||
| import ( | ||
| "context" | ||
| "github.com/open-feature/go-sdk/openfeature" | ||
| ) | ||
|
|
||
| // Set evaluation context with the user's targeting key | ||
| openfeature.SetEvaluationContext( | ||
| openfeature.NewEvaluationContext( | ||
| "user-123", | ||
| map[string]any{}, | ||
| ), | ||
| ) | ||
|
|
||
| client := openfeature.NewClient("my-app") | ||
|
|
||
| // Evaluate the experiment flag | ||
| useNewCheckout, _ := client.BooleanValue( | ||
| context.TODO(), "checkout-experiment", false, openfeature.EvaluationContext{}, | ||
| ) | ||
|
|
||
| if useNewCheckout { | ||
| showNewCheckout() | ||
| } else { | ||
| showExistingCheckout() | ||
| } | ||
|
|
||
| // Track the conversion event — provider links it back to the flag evaluation context | ||
| client.Track( | ||
| context.TODO(), | ||
| "checkout-completed", | ||
| openfeature.EvaluationContext{}, | ||
| openfeature.NewTrackingEventDetails(49.99).Add("currencyCode", "USD"), | ||
| ) | ||
| ``` | ||
|
|
||
| </TabItem> | ||
| </Tabs> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Files:"
git ls-files | rg 'docs/reference/concepts/(07-tracking|08-experimentation)\.mdx$' || true
echo
echo "07-tracking lines around Tabs:"
sed -n '100,220p' docs/reference/concepts/07-tracking.mdx | nl -ba -v100
echo
echo "07-tracking TabItem immediately before code fences:"
python3 - <<'PY'
from pathlib import Path
p=Path('docs/reference/concepts/07-tracking.mdx')
lines=p.read_text().splitlines()
for i,l in enumerate(lines, start=1):
if '<TabItem' in l:
nxt=lines[i] if i < len(lines) else ''
print(f"{i}: {l}")
print(f"next {i+1}: {nxt}")
print("---")
PY
echo
echo "08-experimentation relevant sample around TabItem (if present):"
if [ -f docs/reference/concepts/08-experimentation.mdx ]; then
sed -n '1,120p' docs/reference/concepts/08-experimentation.mdx | nl -ba -v1
echo "---"
python3 - <<'PY'
from pathlib import Path
p=Path('docs/reference/concepts/08-experimentation.mdx')
lines=p.read_text().splitlines()
for i,l in enumerate(lines, start=1):
if '<TabItem' in l:
nxt=lines[i] if i < len(lines) else ''
print(f"{i}: {l}")
print(f"next {i+1}: {nxt}")
print("---")
PY
fi
echo
echo "Common TabItem -> code fence blank line pattern in docs:"
python3 - <<'PY'
from pathlib import Path
missing=[]
for p in Path('docs').rglob('*.mdx'):
lines=p.read_text(encoding='utf-8', errors='replace').splitlines()
for i,l in enumerate(lines, start=1):
if '<TabItem' in l:
nxt=lines[i] if i < len(lines) else ''
if nxt.strip().startswith('```'):
missing.append((str(p), i, nxt))
print(f"TabItem immediate code fences = {len(missing)}")
for p,i,n in missing[:50]:
print(f"{p}:{i}: {n}")
if len(missing)>50:
print(f"... and {len(missing)-50} more")
PYRepository: open-feature/openfeature.dev
Length of output: 332
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "07-tracking lines around Tabs:"
sed -n '100,220p' docs/reference/concepts/07-tracking.mdx | awk '{printf "%6d\t%s\n",$0,$0}'
echo
echo "07-tracking TabItem immediate next lines:"
python3 - <<'PY'
from pathlib import Path
p=Path('docs/reference/concepts/07-tracking.mdx')
lines=p.read_text().splitlines()
for i,l in enumerate(lines, start=1):
if '<TabItem' in l:
nxt=lines[i] if i < len(lines) else ''
blank_after_open='next line blank==' if (nxt == '', i+1) else ''
print(f"{i}: {l}")
print(f"next {i+1}: {nxt!r}")
print()
PY
echo
echo "08-experimentation relevant sample around TabItem:"
sed -n '1,120p' docs/reference/concepts/08-experimentation.mdx | awk '{printf "%6d\t%s\n",$0,$0}'
echo
echo "08-experimentation TabItem immediate next lines:"
python3 - <<'PY'
from pathlib import Path
p=Path('docs/reference/concepts/08-experimentation.mdx')
lines=p.read_text().splitlines()
for i,l in enumerate(lines, start=1):
if '<TabItem' in l:
nxt=lines[i] if i < len(lines) else ''
print(f"{i}: {l}")
print(f"next {i+1}: {nxt!r}")
print()
PY
echo
echo "TabItem immediate code fences across docs:"
python3 - <<'PY'
from pathlib import Path
missing=[]
for p in Path('docs').rglob('*.mdx'):
lines=p.read_text(encoding='utf-8', errors='replace').splitlines()
for i,l in enumerate(lines, start=1):
if '<TabItem' in l:
nxt=lines[i] if i < len(lines) else ''
if nxt.strip().startswith('```'):
missing.append((str(p), i, nxt))
print(f"TabItem immediate code fences = {len(missing)}")
for p,i,n in missing[:80]:
print(f"{p}:{i}: {n}")
if len(missing)>80:
print(f"... and {len(missing)-80} more")
PYRepository: open-feature/openfeature.dev
Length of output: 10668
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "MDX/JSX parser availability:"
npm list mdx `@mdx-js/mdx` 2>/dev/null || true
node -e "try { require.resolve('`@mdx-js/mdx`'); console.log('`@mdx-js/mdx` available'); } catch(e) { console.log('`@mdx-js/mdx` unavailable'); }" 2>&1 || true
echo
echo "Create read-only MDX block-parse probe in temporary writable directory:"
tmpd="$(mktemp -d)"
cd "$tmpd"
cat > probe.js <<'JS'
try {
const { compileSync } = require('`@mdx-js/mdx`');
const input = `<Tabs>
<TabItem value="missing-blank">
\`\`\`ts
const x = 1
\`\`\`
</TabItem>
</Tabs>
`;
const output = compileSync(input, { remarkPlugins: [] });
console.log("no-compile");
console.log(String(output))
console.log("compiled ok")
} catch (/** `@type` {unknown} */ err) {
console.log(String(err.stack ? err.stack : err))
}
JS
node -r /tmp/probe.js probe.js 2>&1 || node probe.js 2>&1 || true
cd /
rm -rf "$tmpd"Repository: open-feature/openfeature.dev
Length of output: 1999
🌐 Web query:
MDX code fence after JSX component opening tag blank line requirement
💡 Result:
In MDX, it is a recommended best practice to include a blank line between a JSX component's opening tag and the content inside it (including fenced code blocks) to ensure the content is correctly parsed as Markdown or block-level elements [1]. When you place a fenced code block immediately after a JSX opening tag without a blank line, MDX may fail to parse the content as intended, often treating it as plain text or encountering a parsing error, because MDX must distinguish between JSX and Markdown blocks [2][1]. This requirement arises from how Markdown and JSX are interleaved, as adhering to this structure helps the parser correctly differentiate between the two [2][3]. For example, the following structure is generally preferred to avoid parsing issues: javascript // This code block will be parsed correctly const greeting = 'Hello, World!'; If you omit the blank line, the content may not be processed as expected, which is a common source of confusion in MDX authoring [1]. While some versions or configurations may handle variations differently, placing tags on their own lines and ensuring a blank line exists between the tag and nested block content remains the most reliable way to prevent rendering and parsing bugs [4][5][1].
Citations:
- 1: https://www.jamdesk.com/utilities/mdx-cheatsheet
- 2: https://mdxjs.com/docs/what-is-mdx/
- 3: RFC: MDX v2 block parsing mdx-js/mdx#1170
- 4: Unable to pass an array of objects in as children to a component in v2 mdx-js/mdx#2243
- 5: https://github.com/mdx-js/mdx/blob/main/docs/docs/troubleshooting-mdx.mdx
🌐 Web query:
MDX 3 parser JSX component followed by fenced code block block quote indentation
💡 Result:
In MDX 3 (which uses the same core micromark-based parser architecture as MDX 2), parsing nested content such as fenced code blocks inside JSX components or block quotes is handled through a state machine that prioritizes specific syntactic constructs [1][2][3]. Key considerations for your structure: 1. Indentation and Fenced Code Blocks: MDX does not support "indented code blocks" (where code is indented by 4 spaces) because this syntax conflicts with the ability to indent JSX components [1][2][3]. You must use fenced code blocks (triple backticks) instead [2][3]. 2. Nesting inside JSX: While MDX supports interleaving Markdown and JSX, complex nesting—specifically putting fenced code blocks deep inside JSX components—can sometimes lead to parsing challenges or unexpected behavior if the indentation levels are excessive or if the closing fence is not correctly aligned [4][5]. The parser expects the closing fence to be able to terminate the block; if the indentation or surrounding JSX tags confuse the boundary, the code block may fail to close properly [4][5]. 3. Block Quotes (>): When using block quotes, the > character is treated as a prefix [6][7]. If a fenced code block is placed inside a block quote, the parser generally handles it as part of that block structure [7]. However, if you are mixing JSX, block quotes, and code blocks, ensure the structure remains standard Markdown compliant, as the MDX parser delegates to the micromark ecosystem [2][3]. 4. Best Practices: - Avoid excessive indentation for fenced code blocks when nested [4]. - If you encounter issues with a code block not closing correctly, try adjusting the indentation of the closing fence or isolating the code block from complex JSX nesting [4][5]. - MDX 3 improvements have generally stabilized these edge cases compared to earlier versions [8]. If a specific configuration fails, it is often due to the ambiguity created by mixing block-level markdown elements inside JSX tags [6][9]. For robust results, keep your fenced code blocks at a consistent, minimal indentation level, and ensure that JSX tags are not unintentionally wrapping or mis-nesting the markdown block content [9].
Citations:
- 1: https://github.com/micromark/mdx-state-machine/blob/master/readme.md
- 2: Rewrite how MDX is parsed mdx-js/mdx#1039
- 3: https://github.com/micromark/mdx-state-machine
- 4: [v2] Fenced code blocks within JSX elements with indent > 2 parses incorrectly mdx-js/mdx#1283
- 5: Stringifying with remark-mdx v2 breaks code blocks inside nested components mdx-js/mdx#1476
- 6: Nested JSX with hanging > mdx-js/mdx#1318
- 7: https://github.com/mdx-js/eslint-mdx/blob/master/packages/eslint-plugin-mdx/src/processors/markdown.ts
- 8: https://github.com/mdx-js/mdx/blob/main/docs/blog/v3.mdx
- 9: https://mdxjs.com/docs/what-is-mdx/
🌐 Web query:
github mdx-js mdx jsx opening tag no blank line fenced code block parser
💡 Result:
In MDX, the parser treats Markdown and JSX as separate entities that must be correctly delimited to be processed successfully [1]. Historically, issues regarding the need for blank lines between JSX tags and other blocks (such as fenced code blocks) were common in MDX v1 [2][3][4]. MDX v2 significantly improved this behavior by introducing a new parser based on micromark, which allows for better interleaving of Markdown and JSX [5][6]. Key takeaways regarding your query: 1. Evolution of Parsing: In MDX v1, "interleaving" was fragile, and developers often needed to include explicit blank lines after an opening JSX tag to ensure the content inside was parsed correctly as Markdown [2][4]. MDX v2, which is the current standard, resolved many of these issues by supporting more flexible interleaving [6]. 2. Structural Requirements: MDX expects JSX components and Markdown blocks to be separated in a way that allows the parser to identify the boundaries of each [1]. If a JSX component is intended to wrap Markdown content, the Markdown inside often requires proper spacing to be recognized as block-level elements [7][6]. 3. Fenced Code Blocks: When placing fenced code blocks inside JSX, they should generally not be heavily indented, as some versions of the parser may interpret excessive indentation incorrectly [8]. The modern MDX parser handles fenced code blocks more reliably than v1, but it is still best practice to ensure the surrounding JSX structure is syntactically valid [5][6]. If you are experiencing parsing errors where a fenced code block immediately follows an opening JSX tag, ensure you are using the latest version of MDX [5]. If the issue persists, adding a blank line is the standard workaround to explicitly signal the start of a new Markdown block to the parser [2][3].
Citations:
- 1: https://mdxjs.com/docs/what-is-mdx/
- 2: Whitespace Required Between React Component and Fenced Code Block mdx-js/mdx#607
- 3: 🏗 Improve JSX block parsing mdx-js/mdx#195
- 4: Markdown content of custom MDX component isn't parsed if empty line isn't present mdx-js/mdx#1312
- 5: Two blank lines within a fenced code block terminates ordered list and breaks code block mdx-js/mdx#1316
- 6: Rewrite how MDX is parsed mdx-js/mdx#1039
- 7: JSX components require a leading newline in MDX v2 but not v1 mdx-js/mdx#1239
- 8: [v2] Fenced code blocks within JSX elements with indent > 2 parses incorrectly mdx-js/mdx#1283
Add a blank line after each TabItem opening tag in the new example.
The four TabItems here start their code fences directly on the next line, while the existing examples in this file and in 08-experimentation.mdx keep one blank line there. Use a blank line before each fenced code block so MDX can clearly distinguish the JSX tag from nested Markdown content.
Proposed fix
<TabItem value="js" label="TypeScript">
+
```ts🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/reference/concepts/07-tracking.mdx` around lines 119 - 242, Add a blank
line immediately after each of the four TabItem opening tags (js, java, csharp,
and go) before its fenced code block, matching the formatting used by the
surrounding examples and 08-experimentation.mdx.
| ```mermaid | ||
| sequenceDiagram | ||
| participant App | ||
| participant OpenFeature SDK | ||
| participant Flag Provider | ||
|
|
||
| App->>OpenFeature SDK: setContext(targetingKey, attributes) | ||
| App->>OpenFeature SDK: getBooleanValue("checkout-experiment", false) | ||
| OpenFeature SDK->>Flag Provider: resolve flag for targetingKey | ||
| Flag Provider-->>OpenFeature SDK: variant (true / false) | ||
| OpenFeature SDK-->>App: variant value | ||
| App->>App: render variant UI | ||
| App->>OpenFeature SDK: track("checkout-completed", details) | ||
| OpenFeature SDK->>Flag Provider: forward tracking event | ||
| Note over Flag Provider: Provider forwards data to your<br/>configured analytics platform | ||
| ``` |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Repository files matching mermaid docs:"
fd -i '.*\.mdx$|.*\.md$' . | sed 's#^\./##' | rg 'docs/reference/concepts/08-experimentation\.mdx|mermaid|sequenceDiagram|participant ' || true
echo
echo "Target excerpt:"
if [ -f docs/reference/concepts/08-experimentation.mdx ]; then
cat -n docs/reference/concepts/08-experimentation.mdx | sed -n '1,80p'
else
echo "file not found"
fi
echo
echo "Search for Mermaid parser availability/version constraints:"
for f in package.json pnpm-lock.yaml package-lock.json yarn.lock bun.lockb; do
if [ -f "$f" ]; then
echo "--- $f ---"
rg -n '"mermaid"|mermaid|`@mermaid`' "$f" || true
fi
done
echo
echo "Extract mermaid blocks in target file:"
python3 - <<'PY'
from pathlib import Path
p=Path('docs/reference/concepts/08-experimentation.mdx')
if not p.exists():
print('target missing')
raise SystemExit
text=p.read_text()
in_block=False
for i,line in enumerate(text.splitlines(),1):
if line.startswith('```mermaid'):
in_block=True
print(f'--- mermaid block lines {i} ---')
elif in_block and line.startswith('```'):
in_block=False
if in_block:
print(f'{i}: {line}')
PYRepository: open-feature/openfeature.dev
Length of output: 5259
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Node availability:"
node --version || true
echo
echo "Try mermaid parser semantics for participant names with spaces:"
node - <<'JS'
const pkg = require('./package.json');
console.log('project mermaid version:', pkg.dependencies.mermaid);
try {
const { mermaid } = require('mermaid');
const code = `
sequenceDiagram
participant App
participant OpenFeature SDK
participant Flag Provider
App->>OpenFeature SDK: setValue(x)
OpenFeature SDK->>Flag Provider: resolve(x, y)
Note over Flag Provider: note text
`;
const renderer = mermaid.parser;
console.log('has mermaid.parser:', !!renderer);
try {
parser.parse(code);
console.log('Parse result: ok');
} catch (e) {
console.log('Parse throws:', e.name, e.message);
}
try {
mermaid.renderSync ? mermaid.renderSync('test', code) : null;
console.log('renderSync result: ok');
} catch (e) {
console.log('renderSync throws:', e.name, e.message);
}
} catch (e) {
console.log('Cannot load mermaid module:', e && e.message ? e.message : e);
}
JSRepository: open-feature/openfeature.dev
Length of output: 393
🌐 Web query:
Mermaid 11 sequenceDiagram participant names spaces alias required parse "OpenFeature SDK"
💡 Result:
In Mermaid sequence diagrams, aliases are the recommended and required way to handle participant names that contain spaces [1][2]. The standard syntax for defining a participant with a display label containing spaces is: participant [ID] as [Display Label with Spaces] For example: sequenceDiagram participant A as Alice Johnson A->>John: Hello John In this syntax, [ID] serves as the internal identifier used to reference the participant in message interactions (e.g., A->>John), while [Display Label with Spaces] is the string rendered in the diagram, which can contain spaces and special characters [1][2]. If you attempt to use a name with spaces directly in a participant declaration or message without an alias, the parser may interpret the spaces as delimiters, leading to syntax errors or unintended rendering of multiple participants [3]. While the OpenFeature SDK is mentioned in your request, Mermaid's parsing logic for sequence diagrams is independent of any specific SDK; however, if you are generating Mermaid code programmatically via an OpenFeature-related tool or any other library, you must ensure the generated string adheres to the alias pattern above to support spaces in labels [1][2]. Key considerations: - Aliases are mandatory for names with spaces [1][4]. - The ID used in the alias definition (e.g., A) must be used in all subsequent message arrows, not the display label [5]. - Known limitations exist when trying to combine aliases with certain configuration types (e.g., stereotypes like boundary, control, entity) on the same line, though these are typically handled by defining the type configuration separately [6].
Citations:
- 1: https://www.mermaidflow.app/docs/syntax/sequence-diagram
- 2: https://mermaid.ai/open-source/syntax/sequenceDiagram.html
- 3: no triming participant name and the name following spaces is as another actor in sequence mermaid-js/mermaid#809
- 4: https://docs.mermaidviewer.com/diagrams/sequence.html
- 5: Aliases for sequence diagrams are rendered as new actors instead of references mermaid-js/mermaid#3758
- 6: Cannot combine alias and actor/participant type in Sequence Diagrams mermaid-js/mermaid#6953
🌐 Web query:
Mermaid sequenceDiagram parser BNF participant declaration spaces quote support participant "OpenFeature SDK"
💡 Result:
In Mermaid sequence diagrams, participant names can include spaces if defined correctly, typically using aliases [1][2]. The standard declaration syntax is 'participant [ID] as [Label]', where the label can contain spaces [1][2]. While the core parser handles these names, the specific BNF grammar is managed internally by the Mermaid codebase; however, for general usage, explicit 'participant' or 'actor' statements are the recommended way to handle names with spaces or complex identifiers [2][3]. Regarding OpenFeature, there is no direct functional integration or specific 'OpenFeature SDK' parser within Mermaid. The OpenFeature documentation uses Mermaid diagrams (such as flowchart or sequence diagrams) to illustrate architecture or concepts [4], but the OpenFeature SDKs themselves do not include a parser for Mermaid syntax, nor does Mermaid natively parse OpenFeature SDK code [5][6][7]. The two technologies serve different purposes: Mermaid for visualization and OpenFeature for feature flag management [4][7].
Citations:
- 1: https://mermaid.ai/open-source/syntax/sequenceDiagram.html
- 2: https://www.mermaidflow.app/docs/syntax/sequence-diagram
- 3: https://www.mermaideditor.io/learn/sequence-diagram-guide
- 4: https://github.com/open-feature/spec/blob/main/specification/appendix-a-included-utilities.md
- 5: https://openfeature.dev/docs/reference/sdks/client/web/
- 6: https://openfeature.dev/docs/reference/sdks/server/javascript/
- 7: https://github.com/open-feature/spec?tab=readme-ov-file
🌐 Web query:
Mermaid 11 sequenceDiagram spaces participant syntax "participant A B"
💡 Result:
In Mermaid 11, participant names that contain spaces cannot be referenced directly in message lines [1][2]. To use a participant with a name containing spaces, you must define an alias for it using the 'as' keyword during declaration [3][4]. The correct syntax is: participant Alias as Full Participant Name After defining the alias, you must use the alias (e.g., 'Alias') in your sequence message lines rather than the full name [1][2]. Example: sequenceDiagram participant A as Alice Smith participant B as Bob Jones A->>B: Hello! If you attempt to use the full name 'Alice Smith' directly in a message like 'Alice Smith->>Bob Jones: Hello!', the parser will not correctly recognize it as the intended participant and will cause a syntax error [1][2]. Recent updates in Mermaid (e.g., PR #7055) have improved error handling for these scenarios to prevent browser instability [5].
Citations:
- 1: https://wildandfreetools.com/blog/mermaid-sequence-diagram-syntax-complete-guide/
- 2: https://github.com/ccheney/robust-skills/blob/main/skills/mermaid-diagrams/references/SEQUENCE.md
- 3: https://mermaid.ai/open-source/syntax/sequenceDiagram.html
- 4: https://www.mintlify.com/mermaid-js/mermaid/diagrams/sequence-diagram
- 5: 6853: prevent browser freeze caused by invalid participant name in sequenceDiagram mermaid-js/mermaid#7055
Use Mermaid aliases for the multi-word participants.
Declare the participants with aliases, then reference the aliases in each arrow and Note over:
🐛 Proposed fix for the mermaid diagram
sequenceDiagram
participant App
- participant OpenFeature SDK
- participant Flag Provider
+ participant SDK as OpenFeature SDK
+ participant Provider as Flag Provider
- App->>OpenFeature SDK: setContext(targetingKey, attributes)
- App->>OpenFeature SDK: getBooleanValue("checkout-experiment", false)
- OpenFeature SDK->>Flag Provider: resolve flag for targetingKey
- Flag Provider-->>OpenFeature SDK: variant (true / false)
- OpenFeature SDK-->>App: variant value
+ App->>SDK: setContext(targetingKey, attributes)
+ App->>SDK: getBooleanValue("checkout-experiment", false)
+ SDK->>Provider: resolve flag for targetingKey
+ Provider-->>SDK: variant (true / false)
+ SDK-->>App: variant value
App->>App: render variant UI
- App->>OpenFeature SDK: track("checkout-completed", details)
- OpenFeature SDK->>Flag Provider: forward tracking event
- Note over Flag Provider: Provider forwards data to your<br/>configured analytics platform
+ App->>SDK: track("checkout-completed", details)
+ SDK->>Provider: forward tracking event
+ Note over Provider: Provider forwards data to your<br/>configured analytics platform📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ```mermaid | |
| sequenceDiagram | |
| participant App | |
| participant OpenFeature SDK | |
| participant Flag Provider | |
| App->>OpenFeature SDK: setContext(targetingKey, attributes) | |
| App->>OpenFeature SDK: getBooleanValue("checkout-experiment", false) | |
| OpenFeature SDK->>Flag Provider: resolve flag for targetingKey | |
| Flag Provider-->>OpenFeature SDK: variant (true / false) | |
| OpenFeature SDK-->>App: variant value | |
| App->>App: render variant UI | |
| App->>OpenFeature SDK: track("checkout-completed", details) | |
| OpenFeature SDK->>Flag Provider: forward tracking event | |
| Note over Flag Provider: Provider forwards data to your<br/>configured analytics platform | |
| ``` |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/reference/concepts/08-experimentation.mdx` around lines 23 - 38, Update
the Mermaid sequence diagram’s multi-word participants, “OpenFeature SDK” and
“Flag Provider,” to use declared aliases, then replace those participant names
with the aliases in every message arrow and the “Note over” clause while
preserving the diagram’s flow.
|
|
||
| ## Experimentation Workflow | ||
|
|
||
| ### Step 1 : Set the Evaluation Context |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Remove the space before the colon in step headings.
The headings "Step 1 : Set the Evaluation Context", "Step 2 : Evaluate the Experiment Flag", "Step 3 : Track Conversions", and "Step 4 : Analyze Results" each have a space before the colon. Standard English punctuation places the colon directly after the word.
✏️ Proposed fix for heading punctuation
-### Step 1 : Set the Evaluation Context
+### Step 1: Set the Evaluation Context-### Step 2 : Evaluate the Experiment Flag
+### Step 2: Evaluate the Experiment Flag-### Step 3 : Track Conversions
+### Step 3: Track Conversions-### Step 4 : Analyze Results
+### Step 4: Analyze ResultsAlso applies to: 121-121, 198-198, 248-248
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/reference/concepts/08-experimentation.mdx` at line 42, Update the four
step headings in the experimentation documentation to remove the space before
each colon, changing “Step N :” to “Step N:”.
This PR
Addresses the experimentation documentation and messaging improvements
raised in #1362.
08-experimentation.mdx)explaining how the tracking API, hooks, and targeting key work together
for A/B testing and experimentation workflows
(
07-tracking.mdx) showing a complete flag evaluation + conversiontracking flow in TypeScript, Java, C# and Go
intro.mdx)linking to the new concepts page
use case
Related Issues
Closes #1362
Notes
A blog post/tutorial (also suggested in the issue) is left as a
follow-up , happy to take that on in a separate PR once this is reviewed.
Follow-up Tasks
How to test
yarn && yarn submodules yarn start/docs/reference/introand verify the Experimentation sectionappears between Hooks and Events
/docs/reference/concepts/experimentationand verify the newpage renders correctly including the Mermaid diagram and code tabs
/docs/reference/concepts/trackingand verify the newExperimentation-Focused Example section appears at the bottom
appears as the 4th item in the features grid
Screenshots
New experimentation concepts page

Intro page — Experimentation section

Homepage — Built for experimentation

Tracking page — Experimentation-focused example
