This is page 1 of 7. Use http://codebase.md/bucketco/docs/_media/integrations/.gitbook/.gitbook/assets/1a0b50d-image.png?format=md&lines=true&page={x} to view the full context.

# Directory Structure

```
├── .gitbook
│   ├── assets
│   │   ├── 03642c5-dwFrame_201 (1).png
│   │   ├── 03642c5-dwFrame_201.png
│   │   ├── 1753259671871 (1).jpeg
│   │   ├── 1a0b50d-image.png
│   │   ├── 1a439d9-image.png
│   │   ├── 2506596-Customized_Widgets.png
│   │   ├── 342658e-image.png
│   │   ├── 4017197-image.png
│   │   ├── 43e55f0-image.png
│   │   ├── 4783e3f-image.png
│   │   ├── 5b0ce63-image (1).png
│   │   ├── 5b0ce63-image.png
│   │   ├── 630b5e9-image.png
│   │   ├── 8bf8a6e-Frame_201.png
│   │   ├── 9efd67c-image.png
│   │   ├── aa37226-image.png
│   │   ├── Access (1) (1).png
│   │   ├── Access (1).png
│   │   ├── Access (2).png
│   │   ├── Access.png
│   │   ├── Adding features to a feature view-min.png
│   │   ├── Adopted-min.png
│   │   ├── Adoption strategy V2-min.png
│   │   ├── Adoption strategy-min.png
│   │   ├── Advanced targeting rules V2-min.png
│   │   ├── Advanced targeting rules v3-min.png
│   │   ├── Advanced targeting rules-min.png
│   │   ├── aecc6f2-image.png
│   │   ├── amplitude.svg
│   │   ├── An example targeting configuration with two rules.-min.png
│   │   ├── api.svg
│   │   ├── App Settings-min.png
│   │   ├── Automated feedback surveys settings v3-min.png
│   │   ├── Automated feedback surveys settings-min.png
│   │   ├── Automated feedback surveys-min.png
│   │   ├── aws-s3.svg
│   │   ├── be124cd-dwdwFrame_201 (1).png
│   │   ├── be124cd-dwdwFrame_201.png
│   │   ├── ccc4f9e-image.png
│   │   ├── CleanShot 2024-06-11 at 8 .25.53@2x.png
│   │   ├── CleanShot 2024-11-22 at 8 .29.42@2x.png
│   │   ├── CleanShot 2024-11-22 at 8 .31.17@2x.png
│   │   ├── CleanShot 2024-11-25 at 9 .28.08@2x.png
│   │   ├── CleanShot 2024-11-25 at 9 .33.10@2x.png
│   │   ├── CleanShot 2024-11-25 at 9 .35.11@2x.png
│   │   ├── CleanShot 2024-11-27 at 10 .45.59@2x.png
│   │   ├── CleanShot 2024-11-27 at 10 .46.36@2x.png
│   │   ├── CleanShot 2024-11-27 at 10 .47.14@2x.png
│   │   ├── CleanShot 2024-11-27 at 10 .50.48@2x.png
│   │   ├── CleanShot 2025-01-07 at 1 .19.36@2x.png
│   │   ├── CleanShot 2025-01-07 at 1 .21.09@2x.png
│   │   ├── CleanShot 2025-01-07 at 1 .22.27@2x.png
│   │   ├── CleanShot 2025-01-07 at 12 .34.32@2x.png
│   │   ├── CleanShot 2025-01-07 at 12 .39.12@2x (1).png
│   │   ├── CleanShot 2025-01-07 at 12 .39.12@2x.png
│   │   ├── CleanShot 2025-01-09 at 10 .56.14@2x.png
│   │   ├── CleanShot 2025-01-09 at 11 .11.54@2x (1).png
│   │   ├── CleanShot 2025-01-09 at 11 .11.54@2x.png
│   │   ├── CleanShot 2025-01-09 at 9 .44.28@2x.png
│   │   ├── CleanShot 2025-01-23 at 1 .48.30@2x.png
│   │   ├── CleanShot 2025-01-23 at 1 .49.29@2x.png
│   │   ├── CleanShot 2025-01-23 at 1 .49.55@2x.png
│   │   ├── CleanShot 2025-01-23 at 2 .10.23@2x.png
│   │   ├── CleanShot 2025-05-09 at 1 .29.05@2x.png
│   │   ├── CleanShot 2025-10-09 at 10 .23.21@2x.png
│   │   ├── Companies Tab-min.png
│   │   ├── Companies-min.png
│   │   ├── company example v2-min (1).png
│   │   ├── company example v2-min.png
│   │   ├── company example v3-min.png
│   │   ├── Company segment filters-min.png
│   │   ├── Create a new environment-min.png
│   │   ├── Creating and managing apps-min.png
│   │   ├── cursor-mcp-demo_h264.mp4
│   │   ├── datadog.svg
│   │   ├── Debugger-min (1).png
│   │   ├── Debugger-min (2).png
│   │   ├── Debugger-min.png
│   │   ├── Enabling Feedback Surveys-min.png
│   │   ├── Environments Page V2-min.png
│   │   ├── Environments Switcher-min.png
│   │   ├── Environments-min.png
│   │   ├── Evaluate Feature.png
│   │   ├── example 1 (1).png
│   │   ├── example 1.png
│   │   ├── example 2 (1).png
│   │   ├── example 2.png
│   │   ├── ezgif-242d06617aea38.gif
│   │   ├── Feature Tab-min.png
│   │   ├── Feature targeting rules example v2-min.png
│   │   ├── Feature targeting rules example V2-min.png
│   │   ├── Feature targeting rules example v3-min.png
│   │   ├── Feature targeting rules example-min.png
│   │   ├── Feature targeting rules UI V2-min.png
│   │   ├── Feature targeting rules UI v3-min.png
│   │   ├── Feature targeting rules UI-min.png
│   │   ├── Feature usage configuration-v2-min.png
│   │   ├── Feature view.png
│   │   ├── feature-flag-list-rum-event.d9c1c876a34458edc70d1317efaec05b.png.avif
│   │   ├── Feature-targeting-rules-v2-min.png
│   │   ├── Features Page V2-min (1).png
│   │   ├── Features Page V2-min.png
│   │   ├── Features Page-min.png
│   │   ├── Features-min.png
│   │   ├── Feedback Tab V2-min.png
│   │   ├── Feedback-min.png
│   │   ├── Getting started-min.png
│   │   ├── gitbook-logo.svg
│   │   ├── github-logo.svg
│   │   ├── Global settings - Feature views-min.png
│   │   ├── Global settings - Manual Targeting-min.png
│   │   ├── Global settings - Release Stages Editing V4-min.png
│   │   ├── Global settings - Release Stages-min.png
│   │   ├── Goal Form.png
│   │   ├── How to use release stages v2-min.png
│   │   ├── How to use release stages-min (1).png
│   │   ├── How to use release stages-min.png
│   │   ├── https___content.gitbook.com_content_pgXAy2Cgsm5pON9oJ06m_blobs_6wGbrQlJPE4JllBuIhla_image (1).png
│   │   ├── image (1) (1).png
│   │   ├── image (1) (2).png
│   │   ├── image (1).png
│   │   ├── image (10).png
│   │   ├── image (11).png
│   │   ├── image (12).png
│   │   ├── image (13).png
│   │   ├── image (14).png
│   │   ├── image (15).png
│   │   ├── image (16).png
│   │   ├── image (17).png
│   │   ├── image (18).png
│   │   ├── image (19).png
│   │   ├── image (2) (1).png
│   │   ├── image (2).png
│   │   ├── image (20).png
│   │   ├── image (21).png
│   │   ├── image (22).png
│   │   ├── image (23).png
│   │   ├── image (24).png
│   │   ├── image (25).png
│   │   ├── image (26).png
│   │   ├── image (27).png
│   │   ├── image (28).png
│   │   ├── image (29).png
│   │   ├── image (3).png
│   │   ├── image (30).png
│   │   ├── image (31).png
│   │   ├── image (32).png
│   │   ├── image (33).png
│   │   ├── image (4).png
│   │   ├── image (5).png
│   │   ├── image (6).png
│   │   ├── image (7).png
│   │   ├── image (8).png
│   │   ├── image (9).png
│   │   ├── image.png
│   │   ├── Iterate Feature V2.png
│   │   ├── LInear mention.mp4
│   │   ├── linear.svg
│   │   ├── mcp-remote-min.mp4
│   │   ├── mcp-remote.mp4
│   │   ├── mixpanel.svg
│   │   ├── Modifying or deleting an app-min.png
│   │   ├── Monitor (1) (1).png
│   │   ├── Monitor (1).png
│   │   ├── Monitor (2).png
│   │   ├── Monitor (3).png
│   │   ├── Monitor (4).png
│   │   ├── Monitor (5).png
│   │   ├── Monitor (6).png
│   │   ├── Monitor (7).png
│   │   ├── Monitor.png
│   │   ├── New feature.png
│   │   ├── next-js.svg
│   │   ├── node-js.svg
│   │   ├── openfeature.svg
│   │   ├── posthog.svg
│   │   ├── Pre-Release.png
│   │   ├── react.svg
│   │   ├── Release Goals.png
│   │   ├── Release Stage Beta Targeting Rules v3-min.png
│   │   ├── Release Stage Beta Targeting Rules V3-min.png
│   │   ├── Release Stage Beta Targeting Rules V5-min.png
│   │   ├── Release Stage Beta Targeting Rules-min.png
│   │   ├── remote config - 3.png
│   │   ├── Remote config.png
│   │   ├── Rolling back flags-V2.png
│   │   ├── Rules in other environments.png
│   │   ├── rum-explorer-error-feature-flag-search.7b9f6c046db1de1c71d279c139f1508a.png.avif
│   │   ├── rum-explorer-session-feature-flag-search.435802460fd607608ad5155f029da57b.png.avif
│   │   ├── Satisfaction feedback-min.png
│   │   ├── Satisified-min.png
│   │   ├── Save the segment-min.png
│   │   ├── Saving New Segment-min.png
│   │   ├── Screenshot 2024-08-14 at 19.25.06 (1).png
│   │   ├── Screenshot 2024-08-14 at 19.25.06.png
│   │   ├── Screenshot 2024-08-15 at 13.57.46.png
│   │   ├── Screenshot 2024-10-10 at 14.04.09.png
│   │   ├── Screenshot 2024-10-10 at 14.04.34.png
│   │   ├── Screenshot 2025-07-10 at 14.04.07.png
│   │   ├── Screenshot 2025-07-10 at 14.11.01.png
│   │   ├── Screenshot 2025-07-10 at 14.29.20.png
│   │   ├── Screenshot 2025-07-15 at 21.31.16.png
│   │   ├── Screenshot 2025-07-21 at 20.07.27.png
│   │   ├── Screenshot 2025-09-02 at 17.08.25.png
│   │   ├── Screenshot 2025-09-02 at 17.10.36 (1).png
│   │   ├── Screenshot 2025-09-02 at 17.10.36 (2).png
│   │   ├── Screenshot 2025-09-02 at 17.10.36.png
│   │   ├── Screenshot 2025-09-02 at 17.11.21 (1).png
│   │   ├── Screenshot 2025-09-02 at 17.11.21.png
│   │   ├── Screenshot 2025-09-02 at 17.13.15 (1).png
│   │   ├── Screenshot 2025-09-02 at 17.13.15.png
│   │   ├── Screenshot 2025-09-02 at 17.19.44 (1).png
│   │   ├── Screenshot 2025-09-02 at 17.19.44.png
│   │   ├── Screenshot 2025-09-09 at 09.32.31.png
│   │   ├── Screenshot 2025-09-12 at 11.50.41.png
│   │   ├── Screenshot 2025-09-12 at 12.30.38.png
│   │   ├── Screenshot 2025-09-12 at 13.14.44.png
│   │   ├── Screenshot 2025-09-12 at 13.18.07.png
│   │   ├── Screenshot 2025-09-12 at 13.21.25.png
│   │   ├── Screenshot 2025-09-12 at 13.25.21.png
│   │   ├── Screenshot 2025-09-12 at 14.29.56.png
│   │   ├── Screenshot 2025-09-12 at 14.37.52.png
│   │   ├── Screenshot 2025-09-12 at 14.58.27.png
│   │   ├── Screenshot 2025-09-12 at 15.00.32.png
│   │   ├── Screenshot 2025-09-12 at 15.01.32.png
│   │   ├── Screenshot 2025-09-12 at 15.03.33.png
│   │   ├── Screenshot 2025-09-12 at 15.04.39.png
│   │   ├── Screenshot 2025-09-12 at 15.06.50.png
│   │   ├── Screenshot 2025-09-12 at 15.13.45.png
│   │   ├── Screenshot 2025-09-12 at 15.14.43.png
│   │   ├── Screenshot 2025-09-12 at 15.16.42.png
│   │   ├── Screenshot 2025-09-12 at 15.18.42.png
│   │   ├── Screenshot 2025-09-12 at 15.32.39.png
│   │   ├── Screenshot 2025-09-12 at 15.33.57.png
│   │   ├── Screenshot 2025-09-12 at 15.35.09.png
│   │   ├── Screenshot 2025-09-12 at 15.36.14.png
│   │   ├── segment (1).svg
│   │   ├── segment.svg
│   │   ├── Segments.png
│   │   ├── Set segment conditions-min.png
│   │   ├── Setting multiple targeting rules.png
│   │   ├── Setting Tab-min.png
│   │   ├── Setting targeting rules v3-min.png
│   │   ├── Setting targeting rules-min.png
│   │   ├── Settings-min (1).png
│   │   ├── Settings-min.png
│   │   ├── slack (1).svg
│   │   ├── Slack (with auto-layout)-min.png
│   │   ├── Slack and Environments-min.png
│   │   ├── Slack and Feature views-min.png
│   │   ├── Slack Integration.png
│   │   ├── Slack Settings under Features-min.png
│   │   ├── Slack with User Feedback.png
│   │   ├── slack.svg
│   │   ├── slackConnected (1).png
│   │   ├── slackConnected.png
│   │   ├── slackDisconnected (1).png
│   │   ├── slackDisconnected.png
│   │   ├── STARS Configuration-min.png
│   │   ├── STARS Feature Funnel-min.png
│   │   ├── STARS Feature Report-min.png
│   │   ├── STARS states.png
│   │   ├── surveys-min.png
│   │   ├── Switching Between Environments-min.png
│   │   ├── Targeting rules interface-min.png
│   │   ├── Targeting rules.png
│   │   ├── There are 5 different types of conditions to chose from-min.png
│   │   ├── Track adoption in the UI V2-min.png
│   │   ├── Track adoption in the UI v3-min.png
│   │   ├── Track adoption in the UI-min.png
│   │   ├── Track new feature V2-min.png
│   │   ├── Tracking Tab-min.png
│   │   ├── ts-js.svg
│   │   ├── type-check-failed.png
│   │   ├── type-check-payload-failed.png
│   │   ├── usage attribute example v3.png
│   │   ├── usage attribute example-min.png
│   │   ├── Usage configuration-min.png
│   │   ├── vercel-logo.svg
│   │   ├── vue-logo.svg
│   │   ├── What is the STARS Framework v3-min.png
│   │   └── What is the STARS Framework_-min.png
│   └── includes
│       ├── integrations.md
│       ├── languages.md
│       ├── need-some-help-chat-with-us.md
│       ├── sdks.md
│       └── untitled.md
├── .github
│   └── README.md
├── .vscode
│   └── settings.json
├── api
│   ├── api-access.md
│   ├── cli.md
│   ├── mcp.md
│   ├── public-api
│   │   ├── public-api-reference.md
│   │   └── README.md
│   └── reflag-rest-api
│       ├── README.md
│       └── reflag-api-reference.md
├── guides
│   ├── self-opt-in.md
│   └── use-reflag-in-your-cli.md
├── integrations
│   ├── amplitude.md
│   ├── aws-s3.md
│   ├── cursor.md
│   ├── datadog.md
│   ├── github.md
│   ├── linear.md
│   ├── mixpanel.md
│   ├── overview.md
│   ├── posthog.md
│   ├── segment.md
│   └── slack.md
├── introduction
│   └── concepts
│       ├── app.md
│       ├── company.md
│       ├── environment.md
│       ├── event.md
│       ├── feature-events.md
│       ├── feature-view.md
│       ├── feature.md
│       ├── feedback.md
│       ├── filter.md
│       ├── README.md
│       ├── release-stage.md
│       ├── segment.md
│       ├── targeting-rules.md
│       └── user.md
├── product-handbook
│   ├── anonymous-users.md
│   ├── concepts
│   │   ├── app.md
│   │   ├── company.md
│   │   ├── environment.md
│   │   ├── event.md
│   │   ├── feature-events.md
│   │   ├── feature-view.md
│   │   ├── feature.md
│   │   ├── feedback.md
│   │   ├── filter.md
│   │   ├── README.md
│   │   ├── release-stage.md
│   │   ├── segment.md
│   │   ├── targeting-rules.md
│   │   └── user.md
│   ├── creating-and-managing-apps
│   │   ├── environments.md
│   │   └── README.md
│   ├── creating-and-managing-apps.md
│   ├── creating-segments.md
│   ├── data-export.md
│   ├── data-residency.md
│   ├── feature-clean-up-and-archival-beta
│   │   ├── ai-code-clean-up-beta.md
│   │   └── README.md
│   ├── feature-entitlements
│   │   ├── README.md
│   │   └── simple-role-based-entitlements.md
│   ├── feature-rollouts
│   │   ├── feature-targeting-rules.md
│   │   └── README.md
│   ├── feature-targeting-rules
│   │   ├── creating-segments.md
│   │   └── environments.md
│   ├── feature-views.md
│   ├── launch-monitor
│   │   ├── automated-feedback-surveys.md
│   │   ├── give-feedback-button.md
│   │   └── README.md
│   ├── product-overview.md
│   ├── remote-config.md
│   ├── self-opt-in.md
│   ├── service-resiliency.md
│   ├── team-permissions.md
│   └── type-safety.md
├── README.md
├── sdk
│   ├── _media
│   │   ├── type-check-failed.png
│   │   └── type-check-payload-failed.png
│   ├── @reflag
│   │   ├── browser-sdk
│   │   │   ├── globals.md
│   │   │   └── README.md
│   │   ├── node-sdk
│   │   │   ├── globals.md
│   │   │   └── README.md
│   │   ├── react-sdk
│   │   │   ├── globals.md
│   │   │   └── README.md
│   │   └── vue-sdk
│   │       ├── globals.md
│   │       └── README.md
│   ├── documents
│   │   ├── browser-sdk
│   │   │   └── FEEDBACK.md
│   │   └── cli
│   │       └── README.md
│   └── README.md
├── SUMMARY.md
├── support
│   └── get-support.md
└── supported-languages
    ├── next.js.md
    ├── openfeature.md
    ├── overview.md
    └── ruby-rails-stimulus.md
```

# Files

--------------------------------------------------------------------------------
/introduction/concepts/README.md:
--------------------------------------------------------------------------------

```markdown
1 | # Data model
2 | 
3 | 
```

--------------------------------------------------------------------------------
/product-handbook/concepts/README.md:
--------------------------------------------------------------------------------

```markdown
1 | # Data model
2 | 
3 | 
```

--------------------------------------------------------------------------------
/product-handbook/creating-and-managing-apps/README.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | description: Learn more about apps in Reflag
 3 | ---
 4 | 
 5 | # Managing apps
 6 | 
 7 | Learn about [apps](../concepts/app.md) here.
 8 | 
 9 | ### Modifying or deleting an app
10 | 
11 | * On the sidebar, click `Settings`
12 | * Under the `App:[App Name]` heading, click `General`
13 | * You can modify the `App name`
14 | * You can delete the app by clicking the `Delete app` button
15 | 
16 | <figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 15.32.39.png" alt="Reflag Global Settings page"><figcaption></figcaption></figure>
17 | 
18 | ### Creating a new app
19 | 
20 | If you have multiple products or applications, you can create additional apps.
21 | 
22 | * Click on `[Current app name]`, found in the top-left corner
23 | * In the tab that appears, click `New app`
24 | * Name the app and click `Create`
25 | 
```

--------------------------------------------------------------------------------
/sdk/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | layout:
  3 |   visible: true
  4 | title:
  5 |   visible: true
  6 | description:
  7 |   visible: false
  8 | tableOfContents:
  9 |   visible: true
 10 | outline:
 11 |   visible: true
 12 | pagination:
 13 |   visible: true
 14 | ---
 15 | 
 16 | # Documentation
 17 | 
 18 | ## Documents
 19 | 
 20 | <table>
 21 | <thead>
 22 | <tr>
 23 | <th>Document</th>
 24 | <th>Description</th>
 25 | </tr>
 26 | </thead>
 27 | <tbody>
 28 | <tr>
 29 | <td>
 30 | 
 31 | [browser-sdk/FEEDBACK](documents/browser-sdk/FEEDBACK.md)
 32 | 
 33 | </td>
 34 | <td>
 35 | 
 36 | &hyphen;
 37 | 
 38 | </td>
 39 | </tr>
 40 | <tr>
 41 | <td>
 42 | 
 43 | [cli/README](documents/cli/README.md)
 44 | 
 45 | </td>
 46 | <td>
 47 | 
 48 | &hyphen;
 49 | 
 50 | </td>
 51 | </tr>
 52 | </tbody>
 53 | </table>
 54 | 
 55 | ## Packages
 56 | 
 57 | <table>
 58 | <thead>
 59 | <tr>
 60 | <th>Package</th>
 61 | <th>Description</th>
 62 | </tr>
 63 | </thead>
 64 | <tbody>
 65 | <tr>
 66 | <td>
 67 | 
 68 | [@reflag/browser-sdk](@reflag/browser-sdk/README.md)
 69 | 
 70 | </td>
 71 | <td>
 72 | 
 73 | &hyphen;
 74 | 
 75 | </td>
 76 | </tr>
 77 | <tr>
 78 | <td>
 79 | 
 80 | [@reflag/node-sdk](@reflag/node-sdk/README.md)
 81 | 
 82 | </td>
 83 | <td>
 84 | 
 85 | &hyphen;
 86 | 
 87 | </td>
 88 | </tr>
 89 | <tr>
 90 | <td>
 91 | 
 92 | [@reflag/react-sdk](@reflag/react-sdk/README.md)
 93 | 
 94 | </td>
 95 | <td>
 96 | 
 97 | &hyphen;
 98 | 
 99 | </td>
100 | </tr>
101 | <tr>
102 | <td>
103 | 
104 | [@reflag/vue-sdk](@reflag/vue-sdk/README.md)
105 | 
106 | </td>
107 | <td>
108 | 
109 | &hyphen;
110 | 
111 | </td>
112 | </tr>
113 | </tbody>
114 | </table>
115 | 
```

--------------------------------------------------------------------------------
/.github/README.md:
--------------------------------------------------------------------------------

```markdown
 1 | <img width="1200" alt="reflag-docs-og" src="https://docs.reflag.com/~gitbook/image?url=https%3A%2F%2F412612722-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Forganizations%252FDu9vflR1aVGOJElT6Sip%252Fsites%252Fsite_RVvaB%252Fsocialpreview%252FQMZvELgHSV06HcHke0HB%252FOG%2520-%2520Docs.jpg%3Falt%3Dmedia%26token%3Dd3b36bf6-20da-475c-84c9-9ae887b7a15d&width=1200&height=630&sign=6f89fdbf&sv=2" />
 2 | 
 3 | <br> Welcome to Reflag, a feature flag provider crafted for SaaS companies.
 4 | 
 5 | Reflag is built to work at the company/organization level right out of the box, is quickly set up, and gives you feature adoption metrics and customer feedback in a beautifully crafted UI.
 6 | 
 7 | **Key features**
 8 | 
 9 | - **Feature flags for B2B**: company-level targeting rules, user aggregation, filtering, segments, and reporting‍
10 | - **Feature entitlements**: grant companies access by flipping a switch
11 | - **Feature remote config**: manage feature configuration with ease in one place
12 | - **Feature adoption metrics**: using a proven and B2B-optimized framework
13 | - **Feature feedback**: using surveys or feedback buttons
14 | - **Feature data export**: sync with your CRM and/or data warehouse
15 | 
16 | **About**
17 | 
18 | This repository syncs the documentation to [docs.reflag.com](https://docs.reflag.com). For SDK docs, please go to the [javascript repository](https://github.com/reflagcom/javascript) repository.
19 | 
20 | ## Quick links
21 | 
22 | - Ready to get started? [Follow the guide](https://docs.reflag.com/introduction/getting-started)
23 | - Need help? [Talk to a founder](https://reflag.com/contact)
24 | - Latest product updates? [See Changelog](https://reflag.com/changelog)
25 | 
26 | Follow us [@bucketdotco on X](https://x.com/bucketdotco) or [@bucket.co on Bluesky](https://bsky.app/profile/bucket.co) for the latest product updates.
27 | 
28 | We're crafting a feature flag management tool for B2B SaaS.
29 | 
```

--------------------------------------------------------------------------------
/product-handbook/launch-monitor/README.md:
--------------------------------------------------------------------------------

```markdown
 1 | # Launch monitor
 2 | 
 3 | Use the launch monitor to track exposure and adoption, and to collect end-user feedback.
 4 | 
 5 | <figure><img src="../../.gitbook/assets/Monitor (7).png" alt=""><figcaption></figcaption></figure>
 6 | 
 7 | ## Exposure
 8 | 
 9 | The Exposed chart shows you the distinct count of companies that have been exposed the the feature. Exposed means that they've been checked for feature access in the SDK and the check returned `enabled`.
10 | 
11 | ## Adoption
12 | 
13 | The Tracked chart shows you the dinstinct count of companies that have interacted with the feature. Interactions are tracked with the `track` method. Here's a code example:
14 | 
15 | ```typescript
16 | import { useFlag } from "@reflag/react-sdk";
17 | 
18 | function StartHuddleButton() {
19 |   const { isLoading, isEnabled, track } = useFlag("huddle");
20 | 
21 |   if (isLoading) {
22 |     return <Loading />;
23 |   }
24 | 
25 |   if (!isEnabled) {
26 |     return null;
27 |   }
28 | 
29 |   return (
30 |     <div>
31 |       Huddles
32 |       <button onClick={() => track()}>Start huddle</button>
33 |     </div>
34 |   );
35 | }
36 | ```
37 | 
38 | ## Feedback
39 | 
40 | You can collect end-user feedback on new feature releases to catch and fix issues faster.
41 | 
42 | ### Static feedback button
43 | 
44 | Here's a brief example using the [Reflag React SDK](../../sdk/@reflag/browser-sdk/) to collect feedback:
45 | 
46 | ```tsx
47 | import { useFlag } from "@reflag/react-sdk";
48 | 
49 | function StartHuddleButton() {
50 |   const { isLoading, isEnabled, requestFeedback } = useFlag("my-feature");
51 | 
52 |   if (isLoading) {
53 |     return <Loading />;
54 |   }
55 | 
56 |   if (!isEnabled) {
57 |     return null;
58 |   }
59 | 
60 |   return (
61 |     <>
62 |       <button>Use feature!</button>
63 |       <button
64 |         onClick={() => requestFeedback({ title: "How do you like <feature>?" })}
65 |       >
66 |         Give feedback!
67 |       </button>
68 |     </>
69 |   );
70 | }
71 | ```
72 | 
73 | ### Automated feedback survey
74 | 
75 | Automated surveys lets you ask for feedback at just the right time after N interactions with the feature. [Learn more here](automated-feedback-surveys.md).
76 | 
```

--------------------------------------------------------------------------------
/product-handbook/feature-clean-up-and-archival-beta/README.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | description: >-
 3 |   Managing feature flag lifecycle on Reflag is straight forward with the
 4 |   "clean-up guide",  notifications and automatic clean-up pull requests.
 5 | ---
 6 | 
 7 | # Feature clean-up and archival
 8 | 
 9 | ## Stale features
10 | 
11 | After features have been rolled out to everyone, they turn stale after a given period of time. Stale features show up with a little broom next to their name and you also receive a Slack notification if the Slack notification is enabled
12 | 
13 | <figure><img src="../../.gitbook/assets/Screenshot 2025-07-15 at 21.31.16.png" alt=""><figcaption></figcaption></figure>
14 | 
15 | ## Stale features view
16 | 
17 | The stale features view lets you see all the features that are currently stale as well as what needs to be done before they can be archived
18 | 
19 | <figure><img src="../../.gitbook/assets/Screenshot 2025-09-02 at 17.19.44 (1).png" alt=""><figcaption></figcaption></figure>
20 | 
21 | ## Clean-up guide
22 | 
23 | Open up a feature and find the built in "Clean-up guide". The "Clean-up guide" helps you through the steps required to safely archive a feature.
24 | 
25 | <figure><img src="../../.gitbook/assets/Screenshot 2025-07-10 at 14.04.07.png" alt="" width="563"><figcaption></figcaption></figure>
26 | 
27 | There are three **checks** that must pass for the feature to be safe to archive:
28 | 
29 | * Stale: Feature was rolled out to everyone some time ago
30 | * Flag removed from the code in a GitHub repository
31 | * No access checks for some time
32 | 
33 | There are two **automations** that can be enabled at the feature level:
34 | 
35 | * Auto-creating a Pull Request once the feature turns stale
36 | * Auto-archiving once all checks pass
37 | 
38 | See the [AI code clean-up](ai-code-clean-up-beta.md) page for more information on automating code clean-up
39 | 
40 | ## Organization clean-up settings
41 | 
42 | In organization settings, you control requirements for each checks to pass:
43 | 
44 | * Configure how soon after rollout features should be considered stale
45 | * If GitHub is connected, you'll see which repository will be checked for the presence of flags
46 | * How long to wait for the last access check
47 | 
48 | You can also set the default automation settings for newly created features.
49 | 
50 | <figure><img src="../../.gitbook/assets/Screenshot 2025-07-10 at 14.11.01.png" alt=""><figcaption></figcaption></figure>
51 | 
52 | 
53 | 
54 | 
```

--------------------------------------------------------------------------------
/api/reflag-rest-api/README.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | description: Introduction to Reflag REST API
 3 | ---
 4 | 
 5 | # Reflag REST API
 6 | 
 7 | ## What is the REST API?
 8 | 
 9 | The Reflag REST API allows developers to programmatically interact with their Reflag accounts.&#x20;
10 | 
11 | By using HTTP requests, such as GET, POST, PUT, and DELETE, users can perform actions like retrieving data, updating account settings, or managing resources without accessing the Reflag web application directly. This enables seamless integration with other systems, automation of tasks, and enhanced flexibility in account management.
12 | 
13 | {% hint style="info" %}
14 | The Reflag REST API serves a different purpose than the Public API. For app integrations, please use the [Public API](../public-api/).
15 | {% endhint %}
16 | 
17 | ## Authentication
18 | 
19 | To begin, generate a new [API key](../api-access.md) from your Reflag app settings. An API key is associated with a specific app and is usable across all environments. It comes with designated scopes that define its capabilities.
20 | 
21 | Pass the API keys to Reflag API through the `Authorization` header using the `bearer` scheme.
22 | 
23 | ## Use Cases
24 | 
25 | This section covers a few simple use cases for the Reflag REST API.
26 | 
27 | ### Toggling Flags
28 | 
29 | The REST API enables customers to integrate their back-office systems with Reflag's flag targeting. By using our API, you can quickly provide access to specific flags for a company or user directly from your systems.
30 | 
31 | Here's a brief guide to enabling the `new-checkout-flow` flag for the `acme-corp` company:
32 | 
33 | ```typescript
34 | await fetch(
35 |   `https://app.reflag.com/api/apps/${appId}/flags/specific-targets/${envId}`,
36 |   {
37 |     method: "PATCH",
38 |     headers: {
39 |       "Content-Type": "application/json",
40 |       "Authorization": `Bearer ${apiToken}`,
41 |     },
42 |     body: JSON.stringify({
43 |       updates: [
44 |         {
45 |           flagKey: "new-checkout-flow",
46 |           value: true,
47 |           companyId: "acme-corp",
48 |         },
49 |       ],
50 |       changeDescription: "Enabled new checkout flow for Acme Corp in prod",
51 |     }),
52 |   }
53 | );
54 | ```
55 | 
56 | #### Automating TypeScript Type Generation with Reflag CLI in CI/CD
57 | 
58 | To automate TypeScript type generation in your CI/CD pipeline, use the Reflag CLI.
59 | 
60 | 1. First, ensure the Reflag CLI is installed and set up in your project.
61 | 2. Second, store the API key in the environment (e.g, action secrets within GitHub).
62 | 
63 | To use the tool in your CI/CD pipeline, simply invoke it as follows:
64 | 
65 | ```sh
66 | # Invoke directly if the environment contains the REFLAG_API_KEY:
67 | npx reflag flags types
68 | 
69 | # Manually specify the key if not in the environment or using a different name:
70 | npx reflag flags types --api-key ${REFLAG_CI_KEY}
71 | ```
72 | 
73 | ## Further Documentation <a href="#install-the-sdk" id="install-the-sdk"></a>
74 | 
75 | For a comprehensive overview of the available Reflag REST API endpoints, refer to the [API Reference](reflag-api-reference.md) section.
76 | 
```

--------------------------------------------------------------------------------
/product-handbook/feature-rollouts/README.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | description: Learn more about feature rollouts in Reflag
 3 | ---
 4 | 
 5 | # Feature rollouts
 6 | 
 7 | You release features gradually to de-risk rollouts. It's better that only a few beta accounts encounter bugs rather than the entire user base.
 8 | 
 9 | Ideally, you first test internally and then roll out a limited release to beta customers. Once you've caught the major bugs or points of confusion, you release the feature to general availability.
10 | 
11 | ## Gradually roll out your feature
12 | 
13 | To roll out a feature in Reflag, you can set access rules.
14 | 
15 | ## Setting access rules
16 | 
17 | [Access rules](feature-targeting-rules.md) on Reflag are designed to simplify the rollout process in B2B companies.
18 | 
19 | The default access criteria are:
20 | 
21 | * Company segments
22 | * Companies
23 | * Users
24 | 
25 | These criteria let you add segments, companies, or users without additional configuration.
26 | 
27 | If you'd like to specify a [rollout percentage](feature-targeting-rules.md#specify-rollout-percentage) or create [advanced access rules](feature-targeting-rules.md#advanced-targeting-rules) using company attributes, user attributes, feature access, or other contexts, you can add additional access rules with the "+ Add rule" button.
28 | 
29 | <figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 13.14.44.png" alt="Setting targeting rules in Reflag"><figcaption></figcaption></figure>
30 | 
31 | ## Using release stages
32 | 
33 | Release stages let you easily signal features' rollout progress to your team and, optionally, set access rules for each stage of the rollout process.
34 | 
35 | Release stages are designed to support the common use case of taking a feature from development to internal testing to a beta testing phase, then finally released to everyone.
36 | 
37 | New apps come with 4 default release stages: In development, Internal, Beta, and General availability.
38 | 
39 | {% hint style="info" %}
40 | Release stages are fully customizable. Go the the [Release stages settings](https://app.reflag.com/env-current/settings/app-stages) to adopt them to your needs.
41 | {% endhint %}
42 | 
43 | #### **In development**
44 | 
45 | When you create a new feature, it is placed in the "In development" stage by default. This release stage signals that a feature is currently being built.
46 | 
47 | #### **Internal**
48 | 
49 | The "Internal" stage signals a feature is ready for internal QA testing.
50 | 
51 | #### **Beta**
52 | 
53 | After internal QA testing is complete, a feature can be moved to the "Beta" stage. This stage signals that a feature is ready to be tested by a limited segment of users.
54 | 
55 | <figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 13.18.07.png" alt="Targeting rules in the Reflag UI"><figcaption></figcaption></figure>
56 | 
57 | #### **General availability**
58 | 
59 | After rolling out a feature to your beta users and making any fixes, you can move to the "General availability" stage. This stage signals that a feature is now live to your general user base.
60 | 
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Getting started
  2 | 
  3 | **Welcome!** Let's get started. We'll do the following:
  4 | 
  5 | 1. Create your first feature flag.
  6 | 2. Install the Reflag SDK.
  7 | 3. Set feature access rules and/or remote configuration.
  8 | 4. Enable Toolbar for local testing
  9 | 5. Monitor your feature launch.
 10 | 
 11 | 
 12 | 
 13 | ## 1. Create your first flag
 14 | 
 15 | Now let's create your first flag.
 16 | 
 17 | {% tabs %}
 18 | {% tab title="CLI" %}
 19 | ```
 20 | npx @reflag/cli new
 21 | ```
 22 | 
 23 | See [CLI docs](sdk/documents/cli/).
 24 | {% endtab %}
 25 | 
 26 | {% tab title="UI" %}
 27 | 1. [Sign up](https://app.reflag.com/) in the app
 28 | 2. Click `New flag` in the sidebar.
 29 | 3. Give your feature a name, and we'll suggest a `flag key` .
 30 | 
 31 | <figure><img src=".gitbook/assets/Screenshot 2025-09-12 at 11.50.41.png" alt=""><figcaption></figcaption></figure>
 32 | {% endtab %}
 33 | 
 34 | {% tab title="MCP" %}
 35 | You can create features from your code editor via our [MCP](api/mcp.md).
 36 | {% endtab %}
 37 | 
 38 | {% tab title="Linear" %}
 39 | You can create features from within Linear by mentioning the `@reflag` [agent](integrations/linear.md).
 40 | {% endtab %}
 41 | {% endtabs %}
 42 | 
 43 | Next, let's set up a Reflag SDK for your language and framework.
 44 | 
 45 | ## 2. Install the Reflag SDK
 46 | 
 47 | Find the supported languages below:
 48 | 
 49 | {% include ".gitbook/includes/sdks.md" %}
 50 | 
 51 | ### Code example for React
 52 | 
 53 | If you've installed the React SDK and have created a feature called `my-new-feature`, getting started will look like the following:
 54 | 
 55 | ```jsx
 56 | import { useFlag } from "@reflag/react-sdk";
 57 | 
 58 | const MyFeature = () => {
 59 |   const { isEnabled } = useFlag("my-new-feature");
 60 | 
 61 |   return isEnabled ? "You have access!" : null;
 62 | };
 63 | ```
 64 | 
 65 | You can now use `isEnabled` to gate access to the feature.
 66 | 
 67 | ## 3. Set access rules
 68 | 
 69 | Head back over to [your dashboard](https://app.reflag.com/), select your feature and the `Access` tab.
 70 | 
 71 | <figure><img src=".gitbook/assets/Access.png" alt=""><figcaption></figcaption></figure>
 72 | 
 73 | From here, you can define segments, companies, and users that will access your feature.
 74 | 
 75 | ## 4. Enable Toolbar for local testing <a href="#next-steps-1" id="next-steps-1"></a>
 76 | 
 77 | In the frontend SDK, enable the Toolbar to toggle features locally.&#x20;
 78 | 
 79 | <figure><img src=".gitbook/assets/CleanShot 2025-10-09 at 10 .23.21@2x.png" alt=""><figcaption></figcaption></figure>
 80 | 
 81 | In the React SDK, you enable it with `toolbar:`
 82 | 
 83 | ```jsx
 84 | <ReflagProvider
 85 |    publishableKey=""
 86 |    context={}
 87 |    toolbar={true}
 88 | >
 89 | ```
 90 | 
 91 | ## 5. Monitor your feature launch <a href="#next-steps-1" id="next-steps-1"></a>
 92 | 
 93 | On the Monitor tab you can track real-time feature exposure, adoption and user feedback.
 94 | 
 95 | <figure><img src=".gitbook/assets/Monitor.png" alt=""><figcaption></figcaption></figure>
 96 | 
 97 | ### Track exposure
 98 | 
 99 | The Exposed chart shows you companies that have been exposed to your feature. This means, companies that have been checked for feature access as per your targeting rules and the check return "enabled".
100 | 
101 | ### Track adoption
102 | 
103 | To track if exposed companies are also interacting with your feature, you can use `track` .
104 | 
105 | See the code example below.
106 | 
107 | ### Get user feedback
108 | 
109 | To get feedback from your users, you can add a [static "Feedback" button](product-handbook/launch-monitor/#static-feedback-button) or you can [trigger a survey](product-handbook/launch-monitor/automated-feedback-surveys.md), at the right time.
110 | 
111 | Here's an example with a static feedback button.
112 | 
113 | ```tsx
114 | import { useFlag } from "@reflag/react-sdk";
115 | 
116 | const MyFeature = () => {
117 |   const { isEnabled, requestFeedback } = useFlag("my-new-feature");
118 | 
119 |   if (!isEnabled) {
120 |     return null;
121 |   }
122 | 
123 |   return (
124 |     <>
125 |       <button onClick={() => track()}>Use feature</button>
126 |       <button
127 |         onClick={() => requestFeedback({ title: "How do you like this new feature?" })}
128 |       >
129 |         Give feedback
130 |       </button>
131 |     </>
132 |   );
133 | }
134 | ```
135 | 
136 | ## Get support
137 | 
138 | * Need some help? [Chat with us](mailto:hello@reflag.com)
139 | * Latest product updates? [See Changelog](https://reflag.com/changelog)
140 | * Create account: [Sign up](https://app.reflag.com/)
141 | 
```

--------------------------------------------------------------------------------
/product-handbook/feature-entitlements/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | description: Learn more about feature entitlements in Reflag
  3 | ---
  4 | 
  5 | # Feature entitlements
  6 | 
  7 | In B2B SaaS, a typical use case is to manage feature access based on the customer’s subscription level. This means enforcing feature access at the company level, not the user level.&#x20;
  8 | 
  9 | This is how Reflag is used to manage feature entitlements.
 10 | 
 11 | ## Why use flags for this use case?
 12 | 
 13 | There are multiple ways to control feature access: You can hard-code it, use a dedicated billing service, or use feature flags.
 14 | 
 15 | If you have a complex billing structure, adding a dedicated service to your stack likely makes the most sense.
 16 | 
 17 | If your billing is relatively straightforward, you can use flags for it. This keeps the number of services to a minimum and lets you roll out new features and manage access from one interface.
 18 | 
 19 | However, not all flagging services are the same. Most are focused on end-users rather than company accounts.&#x20;
 20 | 
 21 | Reflag's feature flagging is purpose-built for B2B with native support for gating features at the company subscription level.
 22 | 
 23 | ## Gate a feature based on subscription plan
 24 | 
 25 | ### Step 1: Initialize Reflag
 26 | 
 27 | Choose [an SDK](broken-reference) to get started, if you haven't already. \
 28 | \
 29 | Reflag needs to know who the authenticated user is and which company they belong to. We attached attribute metadata, such as the company's subscription plan.
 30 | 
 31 | ```tsx
 32 | // identify user
 33 | reflag.user(userId1356, {
 34 |     name: “Rasmus Makwarth”,
 35 | });
 36 | 
 37 | // associate user with company
 38 | reflag.company(companyId51, {
 39 |     name: “Acme Inc.”,
 40 |     plan: “business”,
 41 | });
 42 | ```
 43 | 
 44 | Reflag now understands that Rasmus works for Acme Inc. and Acme Inc. is on the Business subscription plan.
 45 | 
 46 | {% hint style="info" %}
 47 | You can send company attributes as part of the user sign-in event, via a nightly job, or use `updateCompany()`  when the attribute value changes.
 48 | {% endhint %}
 49 | 
 50 | ### Step 2: Group companies by plan
 51 | 
 52 | Next, we need to group companies on the "Business" subscription plan.&#x20;
 53 | 
 54 | We do this using segments. Segments let you group company accounts based on various filters, including company attributes like subscription plans.
 55 | 
 56 | In Reflag, segments are automatically aggregated at the company level. This means creating a segment for "Business" plan customers is as simple as:&#x20;
 57 | 
 58 | Company attribute **"plan**" equals **"business**"
 59 | 
 60 | <figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 14.58.27.png" alt=""><figcaption></figcaption></figure>
 61 | 
 62 | You can do this for all plans. For example:
 63 | 
 64 | * Starter
 65 | * Business
 66 | * Enterprise
 67 | 
 68 | ### Step 3: Gate the feature
 69 | 
 70 | Let’s say you have an export feature that's only available to customers on the "Business" or "Enterprise" plans. To gate this feature with Reflag, you create a new feature called “Export to CSV”. A feature can be as small as a button or as big as a product area.
 71 | 
 72 | Each feature comes with a [feature key](../concepts/feature.md#feature-key), like `export-to-csv`, which you wrap your feature in inside your codebase.&#x20;
 73 | 
 74 | In React, it’d look like this:
 75 | 
 76 | ```tsx
 77 | const { isEnabled } = useFlag("export-to-csv");
 78 | 
 79 | if(isEnabled) { 
 80 | 
 81 |       // access to csv export!
 82 | 
 83 | }
 84 | ```
 85 | 
 86 | With the feature code in, you can now manage access to this feature via the Reflag UI.&#x20;
 87 | 
 88 | In this case, we’ll set the feature access rules to be:&#x20;
 89 | 
 90 | Companies in the segment **Business** or **Enterprise**
 91 | 
 92 | Here’s what that looks like in the Reflag UI:
 93 | 
 94 | <figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 15.00.32.png" alt=""><figcaption></figcaption></figure>
 95 | 
 96 | That’s it!&#x20;
 97 | 
 98 | Every time a company enters either of these segments, they’ll automatically get access to the "Export to CSV" feature. Similarly, if they downgrade, they lose access.
 99 | 
100 | ## Grant individual companies access
101 | 
102 | If you need to grant individual companies access to a feature when they don't have the required subscription plan, you can add them manually.
103 | 
104 | Simply click the "+ Add" button beside the "Companies" label and select the companies you'd like to add from the searchable dropdown.
105 | 
106 | <figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 15.01.32.png" alt=""><figcaption></figcaption></figure>
107 | 
108 | ## How to handle usage-based gating
109 | 
110 | {% hint style="info" %}
111 | This use case isn't yet natively supported by Reflag, but Reflag is flexible enough to handle it in some cases.
112 | {% endhint %}
113 | 
114 | If your features are restricted by plan _and_ usage, like only allowing 1,000 API requests/mo on the Business plan, you can do the following:
115 | 
116 | ### Step 1: Let Reflag know of the current usage&#x20;
117 | 
118 | Send usage metrics to Reflag using company attributes.&#x20;
119 | 
120 | For example, you can send the company's current usage metrics to Reflag at an hourly or daily interval.
121 | 
122 | ```tsx
123 | reflag.companyUpdate(companyId51, {
124 |     apiRequestsCurrentMonth: 793
125 | });
126 | ```
127 | 
128 | ### Step 2: Gate using usage attribute
129 | 
130 | Then, add this custom attribute metric to your access rules.
131 | 
132 | <figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 15.04.39.png" alt=""><figcaption></figcaption></figure>
133 | 
134 | <figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 15.06.50.png" alt=""><figcaption></figcaption></figure>
135 | 
136 | 
```

--------------------------------------------------------------------------------
/sdk/documents/cli/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | layout:
  3 |   visible: true
  4 | title:
  5 |   visible: true
  6 | description:
  7 |   visible: false
  8 | tableOfContents:
  9 |   visible: true
 10 | outline:
 11 |   visible: true
 12 | pagination:
 13 |   visible: true
 14 | ---
 15 | 
 16 | # Reflag CLI
 17 | 
 18 | Command-line interface for interacting with Reflag services. The CLI allows you to manage apps,
 19 | flags, authentication, and generate TypeScript types for your Reflag flags. With this tool,
 20 | you can streamline your flagging workflow directly from your terminal.
 21 | 
 22 | ## Installation
 23 | 
 24 | Install the CLI as a development dependency in your project:
 25 | 
 26 | ```bash
 27 | # npm
 28 | npm install --save-dev @reflag/cli
 29 | 
 30 | # yarn
 31 | yarn add --dev @reflag/cli
 32 | ```
 33 | 
 34 | Run the `new` command from your project's root directory to initialize the CLI, create a flag, and generate TypeScript types in one step:
 35 | 
 36 | ```bash
 37 | # npm
 38 | npx reflag new
 39 | 
 40 | # yarn
 41 | yarn reflag new
 42 | ```
 43 | 
 44 | ## Migrating from Bucket SDK
 45 | 
 46 | If you're migrating from the Bucket CLI, here are the key changes to be aware of:
 47 | 
 48 | - **Command name**: Changed from `bucket` to `reflag`
 49 | - **Type definitions file**: Renamed from `features.d.ts` to `flags.d.ts` (manually remove the old file if it was committed)
 50 | - **Authentication file**: Changed from `.bucket-auth` to `.reflag-auth` (rename or remove the old file)
 51 | - **Configuration file**: Changed from `bucket.config.json` to `reflag.config.json` (rename or remove the old file)
 52 | - **Command**: `features` command is now `flags`
 53 | - **Environment variable**: Use `REFLAG_API_KEY` instead of `BUCKET_API_KEY`
 54 | 
 55 | **Important**: Update your scripts, build steps, and `.gitignore` patterns to reflect these changes.
 56 | 
 57 | ### Individual Commands
 58 | 
 59 | For more control, you can run each command individually:
 60 | 
 61 | ```bash
 62 | # Initialize Reflag in your project (if not already setup)
 63 | npx reflag init
 64 | 
 65 | # Create a new flag
 66 | npx reflag flags create "My Flag"
 67 | 
 68 | # Generate TypeScript types for your flags
 69 | npx reflag flags types
 70 | ```
 71 | 
 72 | ## Configuration
 73 | 
 74 | The CLI creates a `reflag.config.json` file in your project directory when you run `reflag init`. This file contains all the necessary settings for your Reflag integration.
 75 | 
 76 | ### Configuration File Structure
 77 | 
 78 | Here are all the configuration options available in the `reflag.config.json` file:
 79 | 
 80 | ```json
 81 | {
 82 |   "$schema": "https://unpkg.com/@reflag/cli@latest/schema.json",
 83 |   "baseUrl": "https://app.reflag.com",
 84 |   "apiUrl": "https://app.reflag.com/api",
 85 |   "appId": "ap123456789",
 86 |   "typesOutput": [
 87 |     {
 88 |       "path": "gen/flags.d.ts",
 89 |       "format": "react"
 90 |     }
 91 |   ]
 92 | }
 93 | ```
 94 | 
 95 | | Option        | Description                                                                                                                                                          | Default                                            |
 96 | | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
 97 | | `$schema`     | Autocompletion for the config. `latest` can be replaced with a specific version.                                                                                     | "https://unpkg.com/@reflag/cli@latest/schema.json" |
 98 | | `baseUrl`     | Base URL for Reflag services.                                                                                                                                        | "https://app.reflag.com"                           |
 99 | | `apiUrl`      | API URL for Reflag services (overrides baseUrl for API calls).                                                                                                       | "https://app.reflag.com/api"                       |
100 | | `appId`       | Your Reflag application ID.                                                                                                                                          | Required                                           |
101 | | `typesOutput` | Path(s) where TypeScript types will be generated. Can be a string or an array of objects with `path` and `format` properties. Available formats: `react` and `node`. | "gen/flags.ts" with format "react"                 |
102 | 
103 | You can override these settings using command-line options for individual commands.
104 | 
105 | ## Commands
106 | 
107 | ### `reflag init`
108 | 
109 | Initialize a new Reflag configuration in your project. This creates a `reflag.config.json` file with your settings and prompts for any required information not provided via options.
110 | 
111 | ```bash
112 | npx reflag init [--overwrite]
113 | ```
114 | 
115 | Options:
116 | 
117 | - `--overwrite`: Overwrite existing configuration file if one exists.
118 | - `--app-id <id>`: Set the application ID.
119 | - `--key-format <format>`: Set the key format for flags.
120 | 
121 | ### `reflag new [flagName]`
122 | 
123 | All-in-one command to get started quickly. This command combines `init`, flag creation, and type generation in a single step. Use this for the fastest way to get up and running with Reflag.
124 | 
125 | ```bash
126 | npx reflag new "My Flag" [--app-id ap123456789] [--key my-flag]  [--key-format custom] [--out gen/flags.ts] [--format react]
127 | ```
128 | 
129 | Options:
130 | 
131 | - `--key`: Specific key for the flag.
132 | - `--app-id`: App ID to use.
133 | - `--key-format`: Format for flag keys (custom, snake, camel, etc.).
134 | - `--out`: Path to generate TypeScript types.
135 | - `--format`: Format of the generated types (react or node).
136 | 
137 | If you prefer more control over each step, you can use the individual commands (`init`, `flags create`, `flags types`) instead.
138 | 
139 | ### `reflag login`
140 | 
141 | Authenticate with your Reflag account. This stores your credentials securely for subsequent operations.
142 | 
143 | ```bash
144 | npx reflag login
145 | ```
146 | 
147 | ### `reflag logout`
148 | 
149 | Sign out from your Reflag account and remove stored credentials.
150 | 
151 | ```bash
152 | npx reflag logout
153 | ```
154 | 
155 | ### `reflag flags`
156 | 
157 | Manage your Reflag flags with these subcommands:
158 | 
159 | #### `reflag flags create [flagName]`
160 | 
161 | Create a new flag in your Reflag app. The command guides you through the flag creation process with interactive prompts if options are not provided.
162 | 
163 | ```bash
164 | npx reflag flags create "My Flag" [--app-id ap123456789] [--key my-flag] [--key-format custom]
165 | ```
166 | 
167 | Options:
168 | 
169 | - `--key`: Specific key for the flag.
170 | - `--app-id`: App ID to use.
171 | - `--key-format`: Format for flag keys.
172 | 
173 | #### `reflag flags list`
174 | 
175 | List all flags for the current app. This helps you visualize what flags are available and their current configurations.
176 | 
177 | ```bash
178 | npx reflag flags list [--app-id ap123456789]
179 | ```
180 | 
181 | Options:
182 | 
183 | - `--app-id`: App ID to use.
184 | 
185 | #### `reflag flags types`
186 | 
187 | Generate TypeScript types for your flags. This ensures type safety when using Reflag flags in your TypeScript/JavaScript applications.
188 | 
189 | ```bash
190 | npx reflag flags types [--app-id ap123456789] [--out gen/flags.ts] [--format react]
191 | ```
192 | 
193 | Options:
194 | 
195 | - `--app-id`: App ID to use.
196 | - `--out`: Path to generate TypeScript types.
197 | - `--format`: Format of the generated types (react or node).
198 | 
199 | ### `reflag apps`
200 | 
201 | Commands for managing Reflag apps.
202 | 
203 | ## Global Options
204 | 
205 | These options can be used with any command:
206 | 
207 | - `--debug`: Enable debug mode for verbose output.
208 | - `--base-url <url>`: Set the base URL for Reflag API.
209 | - `--api-url <url>`: Set the API URL directly (overrides base URL).
210 | - `--api-key <key>`: Reflag API key for non-interactive authentication.
211 | - `--help`: Display help information for a command.
212 | 
213 | ## AI-Assisted Development
214 | 
215 | Reflag provides powerful AI-assisted development capabilities through rules and Model Context Protocol (MCP). These features help your AI development tools better understand your flags and provide more accurate assistance.
216 | 
217 | ### Reflag Rules (Recommended)
218 | 
219 | The `rules` command helps you set up AI-specific rules for your project. These rules enable AI tools to better understand how to work with Reflag flags and how they should be used in your codebase.
220 | 
221 | ```bash
222 | npx reflag rules [--format <cursor|copilot>] [--yes]
223 | ```
224 | 
225 | Options:
226 | 
227 | - `--format`: Format to add rules in:
228 |   - `cursor`: Adds rules to `.cursor/rules/reflag.mdc` for Cursor IDE integration.
229 |   - `copilot`: Adds rules to `.github/copilot-instructions.md` for GitHub Copilot integration.
230 | - `--yes`: Skip confirmation prompts and overwrite existing files without asking.
231 | 
232 | This command adds rules to your project that provide AI tools with context about how to set up and use Reflag flags. For the copilot format, the rules are added to a dedicated section in the file, allowing you to maintain other copilot instructions alongside Reflag's rules.
233 | 
234 | ## Model Context Protocol
235 | 
236 | The Model Context Protocol (MCP) is an open protocol that provides a standardized way to connect AI models to different data sources and tools. In the context of Reflag, MCP enables your code editor to understand your flags, their states, and their relationships within your codebase. This creates a seamless bridge between your flag management workflow and AI-powered development tools. The MCP server is hosted by Reflag, making it easy to get started.
237 | 
238 | _\*\*Note: The Reflag `mcp` CLI command was previously used for a \_local_ server. However, in recent versions of the Reflag CLI, the `mcp` command has been repurposed to help you connect to the new remote MCP server.\*\*\_
239 | 
240 | ### Setting up MCP
241 | 
242 | The `mcp` command helps you configure your editor or AI client to connect with Reflag's remote MCP server. This allows your AI tools to understand your flags and provide more contextual assistance.
243 | 
244 | ```bash
245 | npx reflag mcp [--editor <editor>] [--scope <local|global>]
246 | ```
247 | 
248 | Options:
249 | 
250 | - `--editor`: The editor/client to configure:
251 |   - `cursor`: [Cursor IDE](https://www.cursor.com/)
252 |   - `vscode`: [Visual Studio Code](https://code.visualstudio.com/)
253 |   - `claude`: [Claude Desktop](https://claude.ai/download)
254 |   - `windsurf`: [Windsurf](https://windsurf.com/editor)
255 | - `--scope`: Whether to configure settings globally or locally for the project.
256 | 
257 | The command will guide you through:
258 | 
259 | 1. Selecting which editor/client to configure.
260 | 2. Choosing which Reflag app to connect to.
261 | 3. Deciding between global or project-local configuration.
262 | 4. Setting up the appropriate configuration file for your chosen editor .
263 | 
264 | _**Note: The setup uses [mcp-remote](https://github.com/geelen/mcp-remote) as a compatibility layer allowing the remote hosted Reflag MCP server to work with all editors/clients that support MCP STDIO servers. If your editor/client supports HTTP Streaming with OAuth you can connect to the Reflag MCP server directly.**_
265 | 
266 | ## Using in CI/CD Pipelines (Beta)
267 | 
268 | The Reflag CLI is designed to work seamlessly in CI/CD pipelines. For automated environments where interactive login is not possible, use the `--api-key` option or specify the API key in the `REFLAG_API_KEY` environment variable.
269 | 
270 | ```bash
271 | # Generate types in CI/CD
272 | npx reflag apps list --api-key $REFLAG_API_KEY
273 | ```
274 | 
275 | **Important restrictions:**
276 | 
277 | - When using `--api-key`, the `login` and `logout` commands are disabled
278 | - API keys bypass all interactive authentication flows
279 | - API keys are bound to one app only. Commands such as `apps list` will only return the bound app
280 | - Store API keys securely using your CI/CD platform's secret management
281 | 
282 | Example CI workflow:
283 | 
284 | ```yaml
285 | # GitHub Actions example
286 | - name: Generate types
287 |   run: npx reflag flags types --api-key ${{ secrets.REFLAG_API_KEY }}
288 | 
289 | # GitHub Actions example (using environment):
290 | - name: Generate types (environment)
291 |   run: npx reflag flags types
292 |   env:
293 |     REFLAG_API_KEY: ${{ secrets.REFLAG_CI_API_KEY }}
294 | ```
295 | 
296 | ## Development
297 | 
298 | ```bash
299 | # Build the CLI
300 | yarn build
301 | 
302 | # Run the CLI locally
303 | yarn reflag [command]
304 | 
305 | # Lint and format code
306 | yarn lint
307 | yarn format
308 | ```
309 | 
310 | ## Requirements
311 | 
312 | - Node.js >=18.0.0
313 | 
314 | ## License
315 | 
316 | > MIT License
317 | > Copyright (c) 2025 Bucket ApS
318 | 
```

--------------------------------------------------------------------------------
/api/public-api/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | description: Introduction to Reflag Public API
  3 | ---
  4 | 
  5 | # Public API
  6 | 
  7 | ## What is the Public API?
  8 | 
  9 | Our public API utilizes JSON over HTTP, allowing both browsers and backend services to access flag data and share information, including companies, users, and events.
 10 | 
 11 | ## Authentication
 12 | 
 13 | To start, you need to obtain either a [_publishable_ or _secret_ SDK key](../api-access.md) from within your Reflag app settings.
 14 | 
 15 | Publishable keys can be either passed in the `Authorization` header using the `bearer` scheme, or as a query parameter when calling our Public API. Secret keys, on the other hand, can only be passed in the  `Authorization` header:
 16 | 
 17 | ```
 18 | // using headers
 19 | Authorization: Bearer <secret_or_publishable_key>
 20 | 
 21 | // using query argument
 22 | GET /features/enabled?publishableKey=<publishable_key>
 23 | ```
 24 | 
 25 | ## Global Infrastructure
 26 | 
 27 | The Public API currently resides at: `https://front.reflag.com/` and `https://front-eu.reflag.com`&#x20;
 28 | 
 29 | Requests to the front-facing API are automatically routed to a data center near you and should thus have a relatively low latency regardless of where your customers are located.
 30 | 
 31 | {% hint style="info" %}
 32 | Contact us if your customers often experience latency over `100ms`. We're happy to help by establishing a closer point of presence.
 33 | {% endhint %}
 34 | 
 35 | {% hint style="warning" %}
 36 | Use `https://front-eu.reflag.com` to ensure your requests are processed by an EU-based server, addressing regulatory concerns.
 37 | {% endhint %}
 38 | 
 39 | ## API Endpoints
 40 | 
 41 | This section provides a streamlined overview of the API endpoints available through Reflag. Each endpoint is listed with its requirement for either a publishable or secret key, and a brief description of its functionality.
 42 | 
 43 | <table data-full-width="false"><thead><tr><th width="266">Endpoint</th><th width="149" data-type="checkbox">Publishable Key</th><th width="121" data-type="checkbox">Secret key</th><th>Description</th></tr></thead><tbody><tr><td><code>GET /features</code></td><td>false</td><td>true</td><td>Retrieve <em>all</em> features with their respective access rules</td></tr><tr><td><code>GET /features/evaluated</code></td><td>true</td><td>true</td><td>Retrieve features that are evaluated for the provided user/company</td></tr><tr><td><code>GET /features/enabled</code></td><td>true</td><td>true</td><td>Retrieve features that are enabled for the provided user/company</td></tr><tr><td><code>POST /features/events</code></td><td>true</td><td>true</td><td>Send events related to feature access</td></tr><tr><td><code>POST /user</code></td><td>true</td><td>true</td><td>Update user in Reflag</td></tr><tr><td><code>POST /company</code></td><td>true</td><td>true</td><td>Update company in Reflag</td></tr><tr><td><code>POST /event</code></td><td>true</td><td>true</td><td>Send events related to feature usage or user actions</td></tr><tr><td><code>POST /bulk</code></td><td>true</td><td>true</td><td>Send multiple calls in bulk.</td></tr></tbody></table>
 44 | 
 45 | {% hint style="info" %}
 46 | To successfully make a POST request, ensure that the API receives data in JSON format. Set the `Content-Type` header to `application/json` for proper processing.
 47 | {% endhint %}
 48 | 
 49 | ### `GET /features`
 50 | 
 51 | This endpoint provides a complete list of flags along with their targeting rules. It's particularly useful for backend SDKs that need to retrieve and evaluate these rules locally. This approach enables determining which flags to activate for a specific user or company, eliminating the need to repeatedly call the `features/enabled` endpoint for each user or company.
 52 | 
 53 | #### Example
 54 | 
 55 | {% code title="Request" %}
 56 | ```http
 57 | GET /features
 58 | Authorization: Bearer <secret_key>
 59 | ```
 60 | {% endcode %}
 61 | 
 62 | {% code title="Response" %}
 63 | ```json
 64 | {
 65 |   "success": true,
 66 |   "features": [
 67 |     {
 68 |       "key": "huddle",
 69 |       "targeting": {
 70 |         "version": 42,
 71 |         "rules": [
 72 |           {
 73 |             "filter": {
 74 |               "type": "group",
 75 |               "operator": "and",
 76 |               "filters": [
 77 |                 {
 78 |                   "type": "context",
 79 |                   "field": "company.id",
 80 |                   "operator": "IS",
 81 |                   "values": ["acme_inc"],
 82 |                 },
 83 |                 {
 84 |                   "type": "rolloutPercentage",
 85 |                   "partialRolloutAttribute": "company.id",
 86 |                   "partialRolloutThreshold": 100000
 87 |                 }
 88 |               ]
 89 |             }
 90 |           }
 91 |         ]
 92 |       }
 93 |     }
 94 |   ]
 95 | }
 96 | ```
 97 | {% endcode %}
 98 | 
 99 | ### `GET /features/evaluated`
100 | 
101 | This endpoint retrieves a list of flag values evaluated for a particular user or company.
102 | 
103 | {% hint style="info" %}
104 | The endpoint is a `GET` request to ensure that the request can be completed without a `CORS Preflight` request to reduce latency.
105 | {% endhint %}
106 | 
107 | The context must be flattened and provided as query parameters. For instance, given the following nested object:
108 | 
109 | ```typescript
110 | {
111 |     company: {
112 |         id: 42,
113 |     },
114 |     user: {
115 |         id: 99,
116 |     },
117 | }
118 | ```
119 | 
120 | It needs to be flattened out into the following form: `context.company.id=42&context.user.id=99` .
121 | 
122 | #### Example
123 | 
124 | <pre class="language-http" data-title="Request" data-overflow="wrap"><code class="lang-http"><strong>GET https://front.reflag.com/features/enabled?context.company.id=42&#x26;context.user.id=99&#x26;publishableKey=pub_prod_Cqx4DGo1lk3Lcct5NHLjWy
125 | </strong></code></pre>
126 | 
127 | {% code title="Response" %}
128 | ```json
129 | {
130 |   "success": true,
131 |   "features": {
132 |     "huddles": {
133 |       "isEnabled": true,
134 |       "key": "huddles",
135 |       "targetingVersion": 42
136 |     }
137 |   }
138 | }
139 | ```
140 | {% endcode %}
141 | 
142 | {% hint style="danger" %}
143 | Reflag utilizes attributes from the `company` endpoint to identify which features are enabled for specific companies. Ensure all `company` attributes referenced in the `context` are also provided through the `company` endpoint.
144 | {% endhint %}
145 | 
146 | ### `GET /features/enabled`
147 | 
148 | This endpoint is similar to `features/evaluated` but only includes flags that have been evaluated as `true`.
149 | 
150 | ### `POST /features/events`
151 | 
152 | This endpoint is designed to relay flag "check" events for various functions within the Reflag. Check events automatically generated by Reflag SDKs when user code checks if a specific flag is activated.
153 | 
154 | #### Example
155 | 
156 | <pre class="language-http" data-title="Request" data-overflow="wrap"><code class="lang-http"><strong>POST https://front.reflag.com/features/events?publishableKey=pub_prod_Cqx4DGo1lk3Lcct5NHLjWy
157 | </strong><strong>Content-Type: application/json
158 | </strong><strong>
159 | </strong><strong>{
160 | </strong>  "action": "evaluate",
161 |   "key": "feature1",
162 |   "targetingVersion": 42,
163 |   "evalContext": {
164 |     "user": { "id": "john_doe" }, "company": {"id": "acme_inc"} 
165 |   },
166 |   "evalResult": false,
167 |   "evalRuleResults": [false, false],
168 |   "evalMissingFields": ["f1"],
169 | }
170 | </code></pre>
171 | 
172 | ### `POST /user`
173 | 
174 | #### User Endpoint Documentation
175 | 
176 | This endpoint is designed to track individual users within your application. It will create a new user if one doesn't exist or update existing users if their IDs were previously recorded.
177 | 
178 | * **Unique ID**: Use a stable unique identifier, such as a database ID or a stable hash, to reference users.
179 | * **User Attributes**: You can include additional attributes for the user.
180 | 
181 | {% hint style="info" %}
182 | If a user isn't associated with a company, their events will not be taken into account by Reflag in certain situations (such as [Automatic Feedback Surveys](../../product-handbook/launch-monitor/automated-feedback-surveys.md)). See the `POST /company` endpoint for details.
183 | {% endhint %}
184 | 
185 | #### Expected Body
186 | 
187 | <table><thead><tr><th width="377">Field</th><th width="126" data-type="checkbox">Required</th><th>Type</th></tr></thead><tbody><tr><td>userId</td><td>true</td><td>String</td></tr><tr><td>attributes</td><td>false</td><td>Object</td></tr><tr><td>timestamp</td><td>false</td><td>ISO 8601</td></tr></tbody></table>
188 | 
189 | #### Example
190 | 
191 | <pre class="language-http" data-title="Request" data-overflow="wrap"><code class="lang-http"><strong>POST https://front.reflag.com/user?publishableKey=pub_prod_Cqx4DGo1lk3Lcct5NHLjWy
192 | </strong><strong>Content-Type: application/json
193 | </strong><strong>
194 | </strong><strong>{
195 | </strong>  "userId": 1234567890,
196 |   "attributes": {
197 |     "name": "Rasmus Makwarth",
198 |     "custom_property": true,
199 |     "some_number": 12,
200 |     "role": "button-pusher"
201 |   }
202 | }
203 | </code></pre>
204 | 
205 | ### `POST /company`
206 | 
207 | This endpoint is designed to track individual companies _(organizations)_ within your application. It will create a new company if one doesn't exist, or update existing companies if their IDs were previously recorded.
208 | 
209 | * **Unique ID**: Use a stable unique identifier, such as a database ID or a stable hash, to reference companies.
210 | * **Company Attributes**: You can include additional attributes for the company.
211 | * **User ID**:  You can associate a user with a company by providing the `userId`. This is important as flags in Reflag look at company-level data.
212 | 
213 | #### Expected Body
214 | 
215 | <table><thead><tr><th width="358">Field</th><th width="133" data-type="checkbox">Required</th><th>Type</th></tr></thead><tbody><tr><td>companyId</td><td>true</td><td>String</td></tr><tr><td>attributes</td><td>false</td><td>Object</td></tr><tr><td>timestamp</td><td>false</td><td>ISO 8601 String</td></tr><tr><td>userId</td><td>false</td><td>String</td></tr></tbody></table>
216 | 
217 | #### Example
218 | 
219 | To monitor which companies have Slack enabled, set `has_slack_enabled: true` for the desired companies. Then, create a flag in Reflag that uses  `has_slack_enabled` attribute in its targeting rules.
220 | 
221 | {% code title="Request" overflow="wrap" %}
222 | ```http
223 | POST https://front.reflag.com/company?publishableKey=pub_prod_Cqx4DGo1lk3Lcct5NHLjWy
224 | Content-Type: application/json
225 | 
226 | {
227 |   "companyId": 101112231415,
228 |   "attributes": {
229 |     "name": "Acme Corp",
230 |     "domain": "acmeinc.com",
231 |     "plan": "enterprise",
232 |     "monthly_spend": 99,
233 |     "createdAt": "2024-01-01T10:00:00Z"
234 |   },
235 |   "userId": 1234567890
236 | }
237 | ```
238 | {% endcode %}
239 | 
240 | ### `POST /event`
241 | 
242 | In your application, events help you monitor user interactions. It's recommended to focus on a few essential features and those under development. To track an event, invoke this method during user interaction.
243 | 
244 | In general, event names match the keys associated with your flags, allowing Reflag to align these events with the specific flag guarding the triggered code. However, when needed, you can utilize custom events for more tailored workflows.
245 | 
246 | #### Request Body
247 | 
248 | <table><thead><tr><th width="422">Field</th><th width="141.5" data-type="checkbox">Required</th><th>Type</th></tr></thead><tbody><tr><td>event</td><td>true</td><td>String</td></tr><tr><td>userId</td><td>true</td><td>String</td></tr><tr><td>companyId</td><td>false</td><td>String</td></tr><tr><td>attributes</td><td>false</td><td>Object</td></tr><tr><td>timestamp</td><td>false</td><td>ISO 8601</td></tr></tbody></table>
249 | 
250 | #### Example
251 | 
252 | {% code title="Request" overflow="wrap" %}
253 | ```http
254 | POST https://front.reflag.com/event?publishableKey=pub_prod_Cqx4DGo1lk3Lcct5NHLjWy
255 | Content-Type: application/json
256 | 
257 | {
258 |   "event": "Sent message",
259 |   "userId": 1234567890,
260 |   "attributes": {
261 |     "position": "popover",
262 |     "version": 3
263 |   },
264 | }
265 | ```
266 | {% endcode %}
267 | 
268 | ### `POST Feedback`
269 | 
270 | Submit qualitative feedback on a specific feature to complement your quantitative metrics. Collect a 1-5 satisfaction score, qualitative feedback, or both.
271 | 
272 | #### Request Body
273 | 
274 | <table><thead><tr><th>Field</th><th data-type="checkbox">Required</th><th>Type</th></tr></thead><tbody><tr><td>featureId</td><td>true</td><td>String</td></tr><tr><td>userId</td><td>true</td><td>String</td></tr><tr><td>companyId</td><td>false</td><td>String</td></tr><tr><td>score</td><td>false</td><td>Number (1-5)</td></tr><tr><td>comment</td><td>false</td><td>String</td></tr></tbody></table>
275 | 
276 | {% hint style="info" %}
277 | Submit at least one of the optional fields: `score` or `comment`. Feedback is invalid if neither of the two is provided.
278 | {% endhint %}
279 | 
280 | #### Example
281 | 
282 | {% code title="Request" overflow="wrap" %}
283 | ```http
284 | POST https://front.reflag.com/feedback?publishableKey=pub_prod_Cqx4DGo1lk3Lcct5NHLjWy
285 | Content-Type: application/json
286 | 
287 | {
288 |   "key": "flag_key",
289 |   "userId": 1234567890,
290 |   "companyId": 101112231415,
291 |   "score": 4,
292 |   "comment": "It's pretty nice, but I expect slightly more to be fully satisfied"
293 | }
294 | ```
295 | {% endcode %}
296 | 
297 | ## Responses
298 | 
299 | The API returns a `200` status code for successful calls and a `400` status code for errors, including invalid request bodies.
300 | 
301 | {% hint style="info" %}
302 | When you encounter a `400` response code, it indicates an invalid request. The response body includes detailed information useful for debugging. Retry attempts are ineffective without troubleshooting first.
303 | {% endhint %}
304 | 
305 | A `403` response indicates that the provided publishable or secret keys are invalid or not allowed with this endpoint.
306 | 
307 | If you encounter a `500` status code, retry the request. Sending events to Reflag might result in duplicate entries, but this is rare.
308 | 
309 | ## Further Documentation <a href="#install-the-sdk" id="install-the-sdk"></a>
310 | 
311 | For a comprehensive overview of the available Public API endpoints, refer to the [API Reference](public-api-reference.md) section.
312 | 
```

--------------------------------------------------------------------------------
/sdk/@reflag/vue-sdk/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | layout:
  3 |   visible: true
  4 | title:
  5 |   visible: true
  6 | description:
  7 |   visible: false
  8 | tableOfContents:
  9 |   visible: true
 10 | outline:
 11 |   visible: true
 12 | pagination:
 13 |   visible: true
 14 | ---
 15 | 
 16 | # Reflag Vue SDK (beta)
 17 | 
 18 | Vue client side library for [Reflag.com](https://reflag.com)
 19 | 
 20 | Reflag supports flag toggling, tracking flag usage, requesting feedback on features and remotely configuring flags.
 21 | 
 22 | The Reflag Vue SDK comes with the same built-in toolbar as the browser SDK which appears on `localhost` by default.
 23 | 
 24 | ## Install
 25 | 
 26 | Install via npm:
 27 | 
 28 | ```shell
 29 | npm i @reflag/vue-sdk
 30 | ```
 31 | 
 32 | ## Migrating from Bucket SDK
 33 | 
 34 | If you have been using the Bucket SDKs, the following list will help you migrate to Reflag SDK:
 35 | 
 36 | - `Bucket*` classes, and types have been renamed to `Reflag*` (e.g. `BucketClient` is now `ReflagClient`)
 37 | - `Feature*` classes, and types have been renamed to `Feature*` (e.g. `Feature` is now `Flag`, `RawFeatures` is now `RawFlags`)
 38 | - All methods that contained `feature` in the name have been renamed to use the `flag` terminology (e.g. `getFeature` is `getFlag`)
 39 | - The `fallbackFeatures` property in client constructor and configuration files has been renamed to `fallbackFlags`
 40 | - `featureKey` has been renamed to `flagKey` in all methods that accepts that argument
 41 | - The SDKs will not emit `evaluate` and `evaluate-config` events anymore
 42 | - The new cookies that are stored in the client's browser are now `reflag-*` prefixed instead og `bucket-*`
 43 | - The `featuresUpdated` hook has been renamed to `flagsUpdated`
 44 | - The `checkIsEnabled` and `checkConfig` hooks have been removed, use `check` from now on
 45 | 
 46 | To ease in transition to Reflag SDK, some of the old methods have been preserved as aliases to the new methods:
 47 | 
 48 | - `getFeature` method is an alias for `getFlag`
 49 | - `getFeatures` method is an alias for `getFlags`
 50 | - `featuresUpdated` hook is an alias for `flagsUpdated`
 51 | 
 52 | If you are running with strict Content Security Policies active on your website, you will need change them as follows:
 53 | 
 54 | - `connect-src https://front.bucket.co` to `connect-src https://front.reflag.com`
 55 | 
 56 | Finally, if you have customized the look & feel of the Feedback component, update `--bucket-feedback-*` CSS classes to `--reflag-feedback-*`
 57 | 
 58 | ## Get started
 59 | 
 60 | ### 1. Add the `ReflagProvider` context provider
 61 | 
 62 | Add the `ReflagProvider` context provider to your application:
 63 | 
 64 | **Example:**
 65 | 
 66 | ```vue
 67 | <script setup lang="ts">
 68 | import { ReflagProvider } from "@reflag/vue-sdk";
 69 | </script>
 70 | 
 71 | <ReflagProvider
 72 |   :publishable-key="publishableKey"
 73 |   :context="{
 74 |     user: { id: 'user_123', name: 'John Doe', email: 'john@acme.com' },
 75 |     company: { id: 'acme_inc', plan: 'pro' },
 76 |   }"
 77 | >
 78 |   <!-- your app -->
 79 | </ReflagProvider>
 80 | ```
 81 | 
 82 | If using Nuxt, wrap `<ReflagProvider>` in `<ClientOnly>`. `<ReflagProvider>` only renders client-side currently.
 83 | 
 84 | ### 2. Use `useFlag get flag status
 85 | 
 86 | ```vue
 87 | <script setup lang="ts">
 88 | import { useFlag } from "@reflag/vue-sdk";
 89 | 
 90 | const { isEnabled } = useFlag("huddles");
 91 | </script>
 92 | 
 93 | <template>
 94 |   <div v-if="isEnabled">
 95 |     <button>Start huddles!</button>
 96 |   </div>
 97 | </template>
 98 | ```
 99 | 
100 | See [useFlag()](#useflag) for a full example
101 | 
102 | ## Setting context
103 | 
104 | Reflag determines which flags are active for a given `user`, `company`, or `other` context.
105 | You can pass these to the `ReflagProvider` using the `context` prop.
106 | 
107 | ### Using the `context` prop
108 | 
109 | ```vue
110 | <ReflagProvider
111 |   :publishable-key="publishableKey"
112 |   :context="{
113 |     user: { id: 'user_123', name: 'John Doe', email: 'john@acme.com' },
114 |     company: { id: 'acme_inc', plan: 'pro' },
115 |     other: { source: 'web' },
116 |   }"
117 | >
118 |   <!-- your app -->
119 | </ReflagProvider>
120 | ```
121 | 
122 | ### Legacy individual props (deprecated)
123 | 
124 | For backward compatibility, you can still use individual props, but these are deprecated and will be removed in the next major version:
125 | 
126 | ```vue
127 | <ReflagProvider
128 |   :publishable-key="publishableKey"
129 |   :user="{ id: 'user_123', name: 'John Doe', email: 'john@acme.com' }"
130 |   :company="{ id: 'acme_inc', plan: 'pro' }"
131 |   :other-context="{ source: 'web' }"
132 | >
133 |   <!-- your app -->
134 | </ReflagProvider>
135 | ```
136 | 
137 | > [!Important]
138 | > The `user`, `company`, and `otherContext` props are deprecated. Use the `context` prop instead, which provides the same functionality in a more structured way.
139 | 
140 | ### Context requirements
141 | 
142 | If you supply `user` or `company` objects, they must include at least the `id` property otherwise they will be ignored in their entirety.
143 | In addition to the `id`, you must also supply anything additional that you want to be able to evaluate flag targeting rules against.
144 | Attributes which are not properties of the `user` or `company` can be supplied using the `other` property.
145 | 
146 | Attributes cannot be nested (multiple levels) and must be either strings, numbers or booleans.
147 | A number of special attributes exist:
148 | 
149 | - `name` -- display name for `user`/`company`,
150 | - `email` -- the email of the user,
151 | - `avatar` -- the URL for `user`/`company` avatar image.
152 | 
153 | To retrieve flags along with their targeting information, use `useFlag(key: string)` hook (described in a section below).
154 | 
155 | Note that accessing `isEnabled` on the object returned by `useFlag()` automatically
156 | generates a `check` event.
157 | 
158 | ## Remote config
159 | 
160 | Remote config is a dynamic and flexible approach to configuring flag behavior outside of your app – without needing to re-deploy it.
161 | 
162 | Similar to `isEnabled`, each flag accessed using the `useFlag()` hook, has a `config` property. This configuration is managed from within Reflag. It is managed similar to the way access to flags is managed, but instead of the
163 | binary `isEnabled` you can have multiple configuration values which are given to different user/companies.
164 | 
165 | ### Get started with Remote config
166 | 
167 | ```ts
168 | const {
169 |   isEnabled,
170 |   config: { key, payload },
171 | } = useFlag("huddles");
172 | 
173 | // isEnabled: true,
174 | // key: "gpt-3.5",
175 | // payload: { maxTokens: 10000, model: "gpt-3.5-beta1" }
176 | ```
177 | 
178 | `key` is mandatory for a config, but if a flag has no config or no config value was matched against the context, the `key` will be `undefined`. Make sure to check against this case when trying to use the configuration in your application. `payload` is an optional JSON value for arbitrary configuration needs.
179 | 
180 | Note that, similar to `isEnabled`, accessing `config` on the object returned by `useFlag()` automatically
181 | generates a `check` event.
182 | 
183 | ## `<ReflagProvider>` component
184 | 
185 | The `<ReflagProvider>` initializes the Reflag SDK, fetches flags and starts listening for automated feedback survey events. The component can be configured using a number of props:
186 | 
187 | - `publishableKey` is used to connect the provider to an _environment_ on Reflag. Find your `publishableKey` under [environment settings](https://app.reflag.com/env-current/settings/app-environments) in Reflag,
188 | - `context`: An object containing `user`, `company`, and `other` properties that make up the evaluation context used to determine if a flag is enabled or not. `company` and `user` contexts are automatically transmitted to Reflag servers so the Reflag app can show you which companies have access to which flags etc.
189 | - `company`, `user` and `otherContext` (deprecated): Individual props for context. These are deprecated in favor of the `context` prop and will be removed in the next major version.
190 | 
191 |   > [!Note]
192 |   > If you specify `company` and/or `user` they must have at least the `id` property, otherwise they will be ignored in their entirety. You should also supply anything additional you want to be able to evaluate flag targeting against,
193 | 
194 | - `timeoutMs`: Timeout in milliseconds when fetching flags from the server,
195 | - `staleWhileRevalidate`: If set to `true`, stale flags will be returned while refetching flags in the background,
196 | - `expireTimeMs`: If set, flags will be cached between page loads for this duration (in milliseconds),
197 | - `staleTimeMs`: Maximum time (in milliseconds) that stale flags will be returned if `staleWhileRevalidate` is true and new flags cannot be fetched.
198 | 
199 | - `enableTracking`: Set to `false` to stop sending tracking events and user/company updates to Reflag. Useful when you're impersonating a user (defaults to `true`),
200 | - `apiBaseUrl`: Optional base URL for the Reflag API. Use this to override the default API endpoint,
201 | - `appBaseUrl`: Optional base URL for the Reflag application. Use this to override the default app URL,
202 | - `sseBaseUrl`: Optional base URL for Server-Sent Events. Use this to override the default SSE endpoint,
203 | - `debug`: Set to `true` to enable debug logging to the console,
204 | - `toolbar`: Optional [configuration](https://docs.reflag.com/supported-languages/browser-sdk/globals#toolbaroptions) for the Reflag toolbar,
205 | - `feedback`: Optional configuration for feedback collection
206 | 
207 | ### Loading states
208 | 
209 | ReflagProvider lets you define a template to be shown while ReflagProvider is initializing:
210 | 
211 | ```vue
212 | <template>
213 |   <ReflagProvider
214 |     :publishable-key="publishableKey"
215 |     :user="user"
216 |     :company="{ id: 'acme_inc', plan: 'pro' }"
217 |   >
218 |     <template #loading>Loading...</template>
219 |     <StartHuddlesButton />
220 |   </ReflagProvider>
221 | </template>
222 | ```
223 | 
224 | If you want more control over loading screens, `useIsLoading()` returns a `Ref<boolean>` which you can use to customize the loading experience.
225 | 
226 | ## `<ReflagBootstrappedProvider>` component
227 | 
228 | The `<ReflagBootstrappedProvider>` component is a specialized version of `ReflagProvider` designed for server-side rendering and preloaded flag scenarios. Instead of fetching flags on initialization, it uses pre-fetched flags, resulting in faster initial page loads and better SSR compatibility.
229 | 
230 | ### Usage
231 | 
232 | ```vue
233 | <script setup lang="ts">
234 | import { ReflagBootstrappedProvider } from "@reflag/vue-sdk";
235 | 
236 | // Pre-fetched flags (typically from your server/SSR layer)
237 | const bootstrappedFlags = {
238 |   context: {
239 |     user: { id: "user123", name: "John Doe", email: "john@acme.com" },
240 |     company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
241 |   },
242 |   flags: {
243 |     huddles: {
244 |       isEnabled: true,
245 |       config: {
246 |         key: "enhanced",
247 |         payload: { maxParticipants: 50, videoQuality: "hd" },
248 |       },
249 |     },
250 |   },
251 | };
252 | </script>
253 | 
254 | <template>
255 |   <ReflagBootstrappedProvider
256 |     :publishable-key="publishableKey"
257 |     :flags="bootstrappedFlags"
258 |   >
259 |     <StartHuddlesButton />
260 |   </ReflagBootstrappedProvider>
261 | </template>
262 | ```
263 | 
264 | ### Getting bootstrapped flags
265 | 
266 | You'll typically generate the `bootstrappedFlags` object on your server using the Node.js SDK or by fetching from the Reflag API. Here's an example using the Node.js SDK:
267 | 
268 | ```js
269 | // server.js (Node.js/SSR)
270 | import { ReflagClient } from "@reflag/node-sdk";
271 | 
272 | const client = new ReflagClient({
273 |   secretKey: "your-secret-key", // Use secret key on server
274 | });
275 | await client.initialize();
276 | 
277 | // Fetch flags for specific context
278 | const context = {
279 |   user: { id: "user123", name: "John Doe", email: "john@acme.com" },
280 |   company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
281 | };
282 | 
283 | const bootstrappedFlags = client.getFlagsForBootstrap(context);
284 | 
285 | // Pass to your Vue app
286 | ```
287 | 
288 | ### ReflagBootstrappedProvider Props
289 | 
290 | `ReflagBootstrappedProvider` accepts all the same props as `ReflagProvider` except:
291 | 
292 | - `flags`: The pre-fetched flags object containing context and flag data
293 | - All other props available in `ReflagProvider` are supported except `context`, `user`, `company`, and `otherContext` (which are extracted from `flags.context`)
294 | 
295 | If the `flags` prop is not provided or is undefined, the provider will not initialize the client and will render in a non-loading state.
296 | 
297 | ## `<ReflagClientProvider>` component
298 | 
299 | The `<ReflagClientProvider>` is a lower-level component that accepts a pre-initialized `ReflagClient` instance. This is useful for advanced use cases where you need full control over client initialization or want to share a client instance across multiple parts of your application.
300 | 
301 | ### ReflagClientProvider Usage
302 | 
303 | ```vue
304 | <script setup lang="ts">
305 | import { ReflagClient } from "@reflag/browser-sdk";
306 | import { ReflagClientProvider } from "@reflag/vue-sdk";
307 | 
308 | // Initialize the client yourself
309 | const client = new ReflagClient({
310 |   publishableKey: "your-publishable-key",
311 |   user: { id: "user123", name: "John Doe" },
312 |   company: { id: "company456", name: "Acme Inc" },
313 |   // ... other configuration options
314 | });
315 | 
316 | // Initialize the client
317 | await client.initialize();
318 | </script>
319 | 
320 | <template>
321 |   <ReflagClientProvider :client="client">
322 |     <template #loading>Loading...</template>
323 |     <Router />
324 |   </ReflagClientProvider>
325 | </template>
326 | ```
327 | 
328 | ### ReflagClientProvider Props
329 | 
330 | The `ReflagClientProvider` accepts the following props:
331 | 
332 | - `client`: A pre-initialized `ReflagClient` instance
333 | 
334 | ### Slots
335 | 
336 | - `loading`: Optional slot to show while the client is initializing (same as `ReflagProvider`)
337 | 
338 | > [!Note]
339 | > Most applications should use `ReflagProvider` or `ReflagBootstrappedProvider` instead of `ReflagClientProvider`. Only use this component when you need the advanced control it provides.
340 | 
341 | ## Hooks
342 | 
343 | ### `useFlag()`
344 | 
345 | Returns the state of a given flag for the current context. The composable provides access to flags and their configurations.
346 | 
347 | `useFlag()` returns an object with this shape:
348 | 
349 | ```ts
350 | {
351 |   isEnabled: boolean, // is the flag enabled
352 |   track: () => void, // send a track event when the flag is used
353 |   requestFeedback: (...) => void // open up a feedback dialog
354 |   config: {key: string, payload: any},  // remote configuration for this flag
355 |   isLoading: boolean // if you want to manage loading state at the flag level
356 | }
357 | ```
358 | 
359 | Example:
360 | 
361 | ```vue
362 | <script setup lang="ts">
363 | import { useFlag } from "@reflag/vue-sdk";
364 | 
365 | const { isEnabled, track, requestFeedback, config } = useFlag("huddles");
366 | </script>
367 | 
368 | <template>
369 |   <div v-if="isLoading">Loading...</div>
370 |   <div v-else-if="!isEnabled">Flag not available</div>
371 |   <div v-else>
372 |     <button @click="track()">Start huddles!</button>
373 |     <button
374 |       @click="
375 |         (e) =>
376 |           requestFeedback({
377 |             title:
378 |               config.payload?.question ??
379 |               'How do you like the Huddles feature?',
380 |             position: {
381 |               type: 'POPOVER',
382 |               anchor: e.currentTarget as HTMLElement,
383 |             },
384 |           })
385 |       "
386 |     >
387 |       Give feedback!
388 |     </button>
389 |   </div>
390 | </template>
391 | ```
392 | 
393 | See the reference docs for details.
394 | 
395 | ### `useTrack()`
396 | 
397 | `useTrack()` returns a function which lets you send custom events to Reflag. It takes a string argument with the event name and optionally an object with properties to attach the event.
398 | 
399 | Using `track` returned from `useFlag()` calls this track function with the flag key as the event name.
400 | 
401 | ```vue
402 | <script setup lang="ts">
403 | import { useTrack } from "@reflag/vue-sdk";
404 | 
405 | const track = useTrack();
406 | </script>
407 | 
408 | <template>
409 |   <div>
410 |     <button @click="track('Huddles Started', { huddlesType: 'voice' })">
411 |       Start voice huddles!
412 |     </button>
413 |   </div>
414 | </template>
415 | ```
416 | 
417 | ### `useRequestFeedback()`
418 | 
419 | Returns a function that lets you open up a dialog to ask for feedback on a specific feature. This is useful for collecting targeted feedback about specific features.
420 | 
421 | See [Automated Feedback Surveys](https://docs.reflag.com/product-handbook/live-satisfaction) for how to do this automatically, without code.
422 | 
423 | When using the `useRequestFeedback` you must pass the flag key to `requestFeedback`.
424 | The example below shows how to use `position` to ensure the popover appears next to the "Give feedback!" button.
425 | 
426 | ```vue
427 | <script setup lang="ts">
428 | import { useRequestFeedback } from "@reflag/vue-sdk";
429 | 
430 | const requestFeedback = useRequestFeedback();
431 | </script>
432 | 
433 | <template>
434 |   <button
435 |     @click="
436 |       (e) =>
437 |         requestFeedback({
438 |           flagKey: 'huddles',
439 |           title: 'How satisfied are you with file uploads?',
440 |           position: {
441 |             type: 'POPOVER',
442 |             anchor: e.currentTarget as HTMLElement,
443 |           },
444 |           // Optional custom styling
445 |           style: {
446 |             theme: 'light',
447 |             primaryColor: '#007AFF',
448 |           },
449 |         })
450 |     "
451 |   >
452 |     Give feedback!
453 |   </button>
454 | </template>
455 | ```
456 | 
457 | See the [Feedback Documentation](https://github.com/reflagcom/javascript/blob/main/packages/browser-sdk/FEEDBACK.md#manual-feedback-collection) for more information on `requestFeedback` options.
458 | 
459 | ### `useSendFeedback()`
460 | 
461 | Returns a function that lets you send feedback to Reflag. This is useful if you've manually collected feedback through your own UI and want to send it to Reflag.
462 | 
463 | ```vue
464 | <script setup lang="ts">
465 | import { useSendFeedback } from "@reflag/vue-sdk";
466 | 
467 | const sendFeedback = useSendFeedback();
468 | 
469 | const handleSubmit = async (data: FormData) => {
470 |   await sendFeedback({
471 |     flagKey: "reflag-flag-key",
472 |     score: parseInt(data.get("score") as string),
473 |     comment: data.get("comment") as string,
474 |   });
475 | };
476 | </script>
477 | 
478 | <template>
479 |   <form @submit="handleSubmit">
480 |     <!-- form content -->
481 |   </form>
482 | </template>
483 | ```
484 | 
485 | ### `useUpdateUser()`, `useUpdateCompany()` and `useUpdateOtherContext()`
486 | 
487 | These composables return functions that let you update the attributes for the currently set user, company, or other context. Updates to user/company are stored remotely and affect flag targeting, while "other" context updates only affect the current session.
488 | 
489 | ```vue
490 | <script setup lang="ts">
491 | import {
492 |   useUpdateUser,
493 |   useUpdateCompany,
494 |   useUpdateOtherContext,
495 | } from "@reflag/vue-sdk";
496 | 
497 | const updateUser = useUpdateUser();
498 | const updateCompany = useUpdateCompany();
499 | const updateOtherContext = useUpdateOtherContext();
500 | 
501 | const handleUserUpdate = async () => {
502 |   await updateUser({
503 |     role: "admin",
504 |     betaFeatures: "enabled",
505 |   });
506 | };
507 | 
508 | const handleCompanyUpdate = async () => {
509 |   await updateCompany({
510 |     plan: "enterprise",
511 |     employees: 500,
512 |   });
513 | };
514 | 
515 | const handleContextUpdate = async () => {
516 |   await updateOtherContext({
517 |     currentWorkspace: "workspace-123",
518 |     theme: "dark",
519 |   });
520 | };
521 | </script>
522 | 
523 | <template>
524 |   <div>
525 |     <button @click="handleUserUpdate">Update User</button>
526 |     <button @click="handleCompanyUpdate">Update Company</button>
527 |     <button @click="handleContextUpdate">Update Context</button>
528 |   </div>
529 | </template>
530 | ```
531 | 
532 | Note: To change the `user.id` or `company.id`, you need to update the props passed to `ReflagProvider` instead of using these composables.
533 | 
534 | ### `useClient()`
535 | 
536 | Returns the `ReflagClient` used by the `ReflagProvider`. The client offers more functionality that
537 | is not directly accessible through the other composables.
538 | 
539 | ```vue
540 | <script setup>
541 | import { useClient } from "@reflag/vue-sdk";
542 | import { onMounted } from "vue";
543 | 
544 | const client = useClient();
545 | 
546 | console.log(client.getContext());
547 | </script>
548 | 
549 | <template>
550 |   <!-- your component content -->
551 | </template>
552 | ```
553 | 
554 | ### `useIsLoading()`
555 | 
556 | Returns a `Ref<boolean>` to indicate if Reflag has finished loading.
557 | Initially, the value will be `true` if no bootstrap flags have been provided and the client has not be initialized.
558 | 
559 | ```vue
560 | <script setup>
561 | import { useIsLoading } from "@reflag/vue-sdk";
562 | import { Spinner } from "./Spinner";
563 | 
564 | const isLoading = useIsLoading();
565 | </script>
566 | 
567 | <template>
568 |   <!-- your component content -->
569 | </template>
570 | ```
571 | 
572 | ### `useOnEvent()`
573 | 
574 | Vue composable for listening to Reflag client events. This composable automatically handles mounting and unmounting of event listeners.
575 | 
576 | Available events include:
577 | 
578 | - `flagsUpdated`: Triggered when flags are updated
579 | - `track`: Triggered when tracking events are sent
580 | - `feedback`: Triggered when feedback is sent
581 | 
582 | ```vue
583 | <script setup lang="ts">
584 | import { useOnEvent } from "@reflag/vue-sdk";
585 | 
586 | // Listen to flag updates
587 | useOnEvent("flagsUpdated", () => {
588 |   console.log("Flags have been updated");
589 | });
590 | </script>
591 | 
592 | <template>
593 |   <!-- your component content -->
594 | </template>
595 | ```
596 | 
597 | You can also provide a specific client instance if needed:
598 | 
599 | ```vue
600 | <script setup lang="ts">
601 | import { ReflagClient } from "@reflag/browser-sdk";
602 | 
603 | const myReflagClient = new ReflagClient();
604 | 
605 | useOnEvent(
606 |   "flagsUpdated",
607 |   () => {
608 |     console.log("flags updated");
609 |   },
610 |   myReflagClient,
611 | );
612 | </script>
613 | 
614 | <template>
615 |   <!-- your component content -->
616 | </template>
617 | ```
618 | 
619 | ## Content Security Policy (CSP)
620 | 
621 | See [CSP](https://github.com/reflagcom/javascript/blob/main/packages/browser-sdk/README.md#content-security-policy-csp) for info on using Reflag React SDK with CSP
622 | 
623 | ## License
624 | 
625 | MIT License
626 | 
627 | Copyright (c) 2025 Bucket ApS
628 | 
```

--------------------------------------------------------------------------------
/sdk/@reflag/browser-sdk/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | layout:
  3 |   visible: true
  4 | title:
  5 |   visible: true
  6 | description:
  7 |   visible: false
  8 | tableOfContents:
  9 |   visible: true
 10 | outline:
 11 |   visible: true
 12 | pagination:
 13 |   visible: true
 14 | ---
 15 | 
 16 | # Reflag Browser SDK
 17 | 
 18 | Basic client for [Reflag.com](https://reflag.com). If you're using React, you'll be better off with the Reflag React SDK.
 19 | 
 20 | Reflag supports flag toggling, tracking flag usage, [collecting feedback](#qualitative-feedback-on-beta-flags) on flags, and [remotely configuring flags](#remote-config).
 21 | 
 22 | ## Install
 23 | 
 24 | First find your `publishableKey` under [environment settings](https://app.reflag.com/env-current/settings/app-environments) in Reflag.
 25 | 
 26 | The package can be imported or used directly in a HTML script tag:
 27 | 
 28 | A. Import module:
 29 | 
 30 | ```typescript
 31 | import { ReflagClient } from "@reflag/browser-sdk";
 32 | 
 33 | const user = {
 34 |   id: 42,
 35 |   role: "manager",
 36 | };
 37 | 
 38 | const company = {
 39 |   id: 99,
 40 |   plan: "enterprise",
 41 | };
 42 | 
 43 | const reflagClient = new ReflagClient({ publishableKey, user, company });
 44 | 
 45 | await reflagClient.initialize();
 46 | 
 47 | const {
 48 |   isEnabled,
 49 |   config: { payload: question },
 50 |   track,
 51 |   requestFeedback,
 52 | } = reflagClient.getFlag("huddle");
 53 | 
 54 | if (isEnabled) {
 55 |   // Show flag. When retrieving `isEnabled` the client automatically
 56 |   // sends a "check" event for the "huddle" flag which is shown in the
 57 |   // Reflag UI.
 58 | 
 59 |   // On usage, call `track` to let Reflag know that a user interacted with the flag
 60 |   track();
 61 | 
 62 |   // The `payload` is a user-supplied JSON in Reflag that is dynamically picked
 63 |   // out depending on the user/company.
 64 |   const question = payload?.question ?? "Tell us what you think of Huddles";
 65 | 
 66 |   // Use `requestFeedback` to create "Send feedback" buttons easily for specific
 67 |   // flags. This is not related to `track` and you can call them individually.
 68 |   requestFeedback({ title: question });
 69 | }
 70 | 
 71 | // `track` just calls `reflagClient.track(<flagKey>)` to send an event using the same flag key
 72 | // You can also use `track` on the client directly to send any custom event.
 73 | reflagClient.track("huddle");
 74 | 
 75 | // similarly, `requestFeedback` just calls `reflagClient.requestFeedback({flagKey: <flagKey>})`
 76 | // which you can also call directly:
 77 | reflagClient.requestFeedback({ flagKey: "huddle" });
 78 | ```
 79 | 
 80 | B. Script tag (client-side directly in html)
 81 | 
 82 | See [example/browser.html](https://github.com/reflagcom/javascript/tree/main/packages/browser-sdk/example/browser.html) for a working example:
 83 | 
 84 | ```html
 85 | <script src="https://cdn.jsdelivr.net/npm/@reflag/browser-sdk@2"></script>
 86 | <script>
 87 |   const reflag = new ReflagBrowserSDK.ReflagClient({
 88 |     publishableKey: "publishableKey",
 89 |     user: { id: "42" },
 90 |     company: { id: "1" },
 91 |   });
 92 | 
 93 |   reflag.initialize().then(() => {
 94 |     console.log("Reflag initialized");
 95 |     document.getElementById("loading").style.display = "none";
 96 |     document.getElementById("start-huddle").style.display = "block";
 97 |   });
 98 | </script>
 99 | <span id="loading">Loading...</span>
100 | <button
101 |   id="start-huddle"
102 |   style="display: none"
103 |   onClick="reflag.track('Started huddle')"
104 | >
105 |   Click me
106 | </button>
107 | ```
108 | 
109 | ### Init options
110 | 
111 | Supply these to the constructor call:
112 | 
113 | ```typescript
114 | type Configuration = {
115 |   logger: console; // by default only logs warn/error, by passing `console` you'll log everything
116 |   apiBaseUrl?: "https://front.reflag.com";
117 |   sseBaseUrl?: "https://livemessaging.bucket.co";
118 |   feedback?: undefined; // See FEEDBACK.md
119 |   enableTracking?: true; // set to `false` to stop sending track events and user/company updates to Reflag servers. Useful when you're impersonating a user
120 |   fallbackFlags?:
121 |     | string[]
122 |     | Record<string, { key: string; payload: any } | true>; // Enable these flags if unable to contact reflag.com. Can be a list of flag keys or a record with configuration values
123 |   timeoutMs?: number; // Timeout for fetching flags (default: 5000ms)
124 |   staleWhileRevalidate?: boolean; // Revalidate in the background when cached flags turn stale to avoid latency in the UI (default: false)
125 |   staleTimeMs?: number; // at initialization time flags are loaded from the cache unless they have gone stale. Defaults to 0 which means the cache is disabled. Increase this in the case of a non-SPA
126 |   expireTimeMs?: number; // In case we're unable to fetch flags from Reflag, cached/stale flags will be used instead until they expire after `expireTimeMs`. Default is 30 days
127 |   offline?: boolean; // Use the SDK in offline mode. Offline mode is useful during testing and local development
128 | };
129 | ```
130 | 
131 | ## Migrating from Bucket SDK
132 | 
133 | If you have been using the Bucket SDKs, the following list will help you migrate to Reflag SDK:
134 | 
135 | - `Bucket*` classes, and types have been renamed to `Reflag*` (e.g. `BucketClient` is now `ReflagClient`)
136 | - `Feature*` classes, and types have been renamed to `Feature*` (e.g. `Feature` is now `Flag`, `RawFeatures` is now `RawFlags`)
137 | - All methods that contained `feature` in the name have been renamed to use the `flag` terminology (e.g. `getFeature` is `getFlag`)
138 | - The `fallbackFeatures` property in client constructor and configuration files has been renamed to `fallbackFlags`
139 | - `featureKey` has been renamed to `flagKey` in all methods that accepts that argument
140 | - The new cookies that are stored in the client's browser are now `reflag-*` prefixed instead og `bucket-*`
141 | - The `featuresUpdated` hook has been renamed to `flagsUpdated`
142 | - The `checkIsEnabled` and `checkConfig` hooks have been removed, use `check` from now on
143 | 
144 | To ease in transition to Reflag SDK, some of the old methods have been preserved as aliases to the new methods:
145 | 
146 | - `getFeature` method is an alias for `getFlag`
147 | - `getFeatures` method is an alias for `getFlags`
148 | - `featuresUpdated` hook is an alias for `flagsUpdated`
149 | 
150 | If you are running with strict Content Security Policies active on your website, you will need change them as follows:
151 | 
152 | - `connect-src https://front.bucket.co` to `connect-src https://front.reflag.com`
153 | 
154 | Finally, if you have customized the look & feel of the Feedback component, update `--bucket-feedback-*` CSS classes to `--reflag-feedback-*`
155 | 
156 | ## Flag toggles
157 | 
158 | Reflag determines which flags are active for a given user/company. The user/company is given in the ReflagClient constructor.
159 | 
160 | If you supply `user` or `company` objects, they must include at least the `id` property otherwise they will be ignored in their entirety.
161 | In addition to the `id`, you must also supply anything additional that you want to be able to evaluate flag targeting rules against.
162 | 
163 | Attributes cannot be nested (multiple levels) and must be either strings, integers or booleans.
164 | Some attributes are special and used in Reflag UI:
165 | 
166 | - `name` -- display name for `user`/`company`,
167 | - `email` -- is accepted for `user`s and will be highlighted in the Reflag UI if available,
168 | - `avatar` -- can be provided for both `user` and `company` and should be an URL to an image.
169 | 
170 | ```ts
171 | const reflagClient = new ReflagClient({
172 |   publishableKey,
173 |   user: {
174 |     id: "user_123",
175 |     name: "John Doe",
176 |     email: "john@acme.com"
177 |     avatar: "https://example.com/images/udsy6363"
178 |   },
179 |   company: {
180 |     id: "company_123",
181 |     name: "Acme, Inc",
182 |     avatar: "https://example.com/images/31232ds"
183 |   },
184 | });
185 | ```
186 | 
187 | To retrieve flags along with their targeting information, use `getFlag(key: string)`:
188 | 
189 | ```ts
190 | const huddle = reflagClient.getFlag("huddle");
191 | // {
192 | //   isEnabled: true,
193 | //   config: { key: "zoom", payload: { ... } },
194 | //   track: () => Promise<Response>
195 | //   requestFeedback: (options: RequestFeedbackData) => void
196 | // }
197 | ```
198 | 
199 | You can use `getFlags()` to retrieve all enabled flags currently.
200 | 
201 | ```ts
202 | const flags = reflagClient.getFlags();
203 | // {
204 | //   huddle: {
205 | //     isEnabled: true,
206 | //     targetingVersion: 42,
207 | //     config: ...
208 | //   }
209 | // }
210 | ```
211 | 
212 | `getFlags()` is meant to be more low-level than `getFlag()` and it typically used
213 | by down-stream clients, like the React SDK.
214 | 
215 | Note that accessing `isEnabled` on the object returned by `getFlags` does not automatically
216 | generate a `check` event, contrary to the `isEnabled` property on the object returned by `getFlag`.
217 | 
218 | ## Remote config
219 | 
220 | Remote config is a dynamic and flexible approach to configuring flag behavior outside of your app – without needing to re-deploy it.
221 | 
222 | Similar to `isEnabled`, each flag has a `config` property. This configuration is managed from within Reflag.
223 | It is managed similar to the way access to flags is managed, but instead of the binary `isEnabled` you can have
224 | multiple configuration values which are given to different user/companies.
225 | 
226 | ```ts
227 | const flags = reflagClient.getFlags();
228 | // {
229 | //   huddle: {
230 | //     isEnabled: true,
231 | //     targetingVersion: 42,
232 | //     config: {
233 | //       key: "gpt-3.5",
234 | //       payload: { maxTokens: 10000, model: "gpt-3.5-beta1" }
235 | //     }
236 | //   }
237 | // }
238 | ```
239 | 
240 | `key` is mandatory for a config, but if a flag has no config or no config value was matched against the context, the `key` will be `undefined`. Make sure to check against this case when trying to use the configuration in your application. `payload` is an optional JSON value for arbitrary configuration needs.
241 | 
242 | Just as `isEnabled`, accessing `config` on the object returned by `getFlags` does not automatically
243 | generate a `check` event, contrary to the `config` property on the object returned by `getFlag`.
244 | 
245 | ## Server-side rendering and bootstrapping
246 | 
247 | For server-side rendered applications, you can eliminate the initial network request by bootstrapping the client with pre-fetched flag data.
248 | 
249 | ### Init options bootstrapped
250 | 
251 | ```typescript
252 | type Configuration = {
253 |   logger: console; // by default only logs warn/error, by passing `console` you'll log everything
254 |   apiBaseUrl?: "https://front.reflag.com";
255 |   sseBaseUrl?: "https://livemessaging.bucket.co";
256 |   feedback?: undefined; // See FEEDBACK.md
257 |   enableTracking?: true; // set to `false` to stop sending track events and user/company updates to Reflag servers. Useful when you're impersonating a user
258 |   offline?: boolean; // Use the SDK in offline mode. Offline mode is useful during testing and local development
259 |   bootstrappedFlags?: FetchedFlags; // Pre-fetched flags from server-side (see Server-side rendering section)
260 | };
261 | ```
262 | 
263 | ### Using bootstrappedFlags
264 | 
265 | Use the Node SDK's `getFlagsForBootstrap()` method to pre-fetch flags server-side, then pass them to the browser client:
266 | 
267 | ```typescript
268 | // Server-side: Get flags using Node SDK
269 | import { ReflagClient as ReflagNodeClient } from "@reflag/node-sdk";
270 | 
271 | const serverClient = new ReflagNodeClient({ secretKey: "your-secret-key" });
272 | await serverClient.initialize();
273 | 
274 | const { flags } = serverClient.getFlagsForBootstrap({
275 |   user: { id: "user123", name: "John Doe", email: "john@acme.com" },
276 |   company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
277 | });
278 | 
279 | // Pass flags data to client using your framework's preferred method
280 | // or for example in a script tag
281 | app.get("/", (req, res) => {
282 |   res.set("Content-Type", "text/html");
283 |   res.send(
284 |     Buffer.from(
285 |       `<script>var flags = ${JSON.stringify(flags)};</script>
286 |       <main id="app"></main>`,
287 |     ),
288 |   );
289 | });
290 | 
291 | // Client-side: Initialize with pre-fetched flags
292 | import { ReflagClient } from "@reflag/browser-sdk";
293 | 
294 | const reflagClient = new ReflagClient({
295 |   publishableKey: "your-publishable-key",
296 |   user: { id: "user123", name: "John Doe", email: "john@acme.com" },
297 |   company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
298 |   bootstrappedFlags: flags, // No network request needed
299 | });
300 | 
301 | await reflagClient.initialize(); // Initializes all but flags
302 | const { isEnabled } = reflagClient.getFlag("huddle");
303 | ```
304 | 
305 | This eliminates loading states and improves performance by avoiding the initial flags API call.
306 | 
307 | ## Context management
308 | 
309 | ### Updating user/company/other context
310 | 
311 | Attributes given for the user/company/other context in the ReflagClient constructor can be updated for use in flag targeting evaluation with the `updateUser()`, `updateCompany()` and `updateOtherContext()` methods.
312 | They return a promise which resolves once the flags have been re-evaluated follow the update of the attributes.
313 | 
314 | The following shows how to let users self-opt-in for a new flag. The flag must have the rule `voiceHuddleOptIn IS true` set in the Reflag UI.
315 | 
316 | ```ts
317 | // toggle opt-in for the voiceHuddle flag:
318 | const { isEnabled } = reflagClient.getFlag("voiceHuddle");
319 | // this toggles the flag on/off. The promise returns once flag targeting has been
320 | // re-evaluated.
321 | await reflagClient.updateUser({ voiceHuddleOptIn: (!isEnabled).toString() });
322 | ```
323 | 
324 | {% hint style="info" %}
325 | {% endhint %}
326 | 
327 | ### setContext()
328 | 
329 | The `setContext()` method allows you to replace the entire context (user, company, and other attributes) at once. This method is useful when you need to completely change the context, such as when a user logs in or switches between different accounts.
330 | 
331 | ```ts
332 | await reflagClient.setContext({
333 |   user: {
334 |     id: "new-user-123",
335 |     name: "Jane Doe",
336 |     email: "jane@example.com",
337 |     role: "admin",
338 |   },
339 |   company: {
340 |     id: "company-456",
341 |     name: "New Company Inc",
342 |     plan: "enterprise",
343 |   },
344 |   other: {
345 |     feature: "beta",
346 |     locale: "en-US",
347 |   },
348 | });
349 | ```
350 | 
351 | The method will:
352 | 
353 | - Replace the entire context with the new values
354 | - Re-evaluate all flags based on the new context
355 | - Update the user and company information on Reflag servers
356 | - Return a promise that resolves once the flags have been re-evaluated
357 | 
358 | ### getContext()
359 | 
360 | The `getContext()` method returns the current context being used for flag evaluation. This is useful for debugging or when you need to inspect the current user, company, and other attributes.
361 | 
362 | ```ts
363 | const currentContext = reflagClient.getContext();
364 | console.log(currentContext);
365 | // {
366 | //   user: { id: "user-123", name: "John Doe", email: "john@example.com" },
367 | //   company: { id: "company-456", name: "Acme Inc", plan: "enterprise" },
368 | //   other: { locale: "en-US", feature: "beta" }
369 | // }
370 | ```
371 | 
372 | The returned context object contains:
373 | 
374 | - `user`: Current user attributes (if any)
375 | - `company`: Current company attributes (if any)
376 | - `other`: Additional context attributes not related to user or company
377 | 
378 | ## Toolbar
379 | 
380 | The Reflag Toolbar is great for toggling flags on/off for yourself to ensure that everything works both when a flag is on and when it's off.
381 | 
382 | <img width="352" alt="Toolbar screenshot" src="https://github.com/user-attachments/assets/c223df5a-4bd8-49a1-8b4a-ad7001357693" />
383 | 
384 | The toolbar will automatically appear on `localhost`. However, it can also be incredibly useful in production.
385 | You have full control over when it appears through the `toolbar` configuration option passed to the `ReflagClient`.
386 | 
387 | You can pass a simple boolean to force the toolbar to appear/disappear:
388 | 
389 | ```typescript
390 | const client = new ReflagClient({
391 |   // show the toolbar even in production if the user is an internal/admin user
392 |   toolbar: user?.isInternal,
393 |   ...
394 | });
395 | ```
396 | 
397 | You can also configure the position of the toolbar on the screen:
398 | 
399 | ```typescript
400 | const client = new ReflagClient({
401 |   toolbar: {
402 |     show: true;
403 |     position: {
404 |       placement: "bottom-left",
405 |       offset: {x: "1rem", y: "1rem"}
406 |     }
407 |   }
408 |   ...
409 | })
410 | ```
411 | 
412 | See [the reference](https://docs.reflag.com/supported-languages/browser-sdk/globals#toolbaroptions) for details.
413 | 
414 | ## Qualitative feedback on beta flags
415 | 
416 | Reflag can collect qualitative feedback from your users in the form of a [Customer Satisfaction Score](https://en.wikipedia.org/wiki/Customer_satisfaction) and a comment.
417 | 
418 | ### Automated feedback collection
419 | 
420 | The Reflag Browser SDK comes with automated feedback collection mode enabled by default, which lets the Reflag service ask your users for feedback for relevant flags just after they've used them.
421 | 
422 | {% hint style="info" %}
423 | To get started with automatic feedback collection, make sure you've set `user` in the `ReflagClient` constructor.
424 | {% endhint %}
425 | 
426 | Automated feedback surveys work even if you're not using the SDK to send events to Reflag.
427 | It works because the Reflag Browser SDK maintains a live connection to Reflag's servers and can automatically show a feedback prompt whenever the Reflag servers determines that an event should trigger a prompt - regardless of how this event is sent to Reflag.
428 | 
429 | You can find all the options to make changes to the default behavior in the [Reflag feedback documentation](../../documents/browser-sdk/FEEDBACK.md).
430 | 
431 | ### Reflag feedback UI
432 | 
433 | Reflag can assist you with collecting your user's feedback by offering a pre-built UI, allowing you to get started with minimal code and effort.
434 | 
435 | [Read the Reflag feedback UI documentation](../../documents/browser-sdk/FEEDBACK.md)
436 | 
437 | ### Reflag feedback SDK
438 | 
439 | Feedback can be submitted to Reflag using the SDK:
440 | 
441 | ```ts
442 | reflagClient.feedback({
443 |   flagKey: "my-flag-key", // String (required), copy from Flag feedback tab
444 |   score: 5, // Number: 1-5 (optional)
445 |   comment: "Absolutely stellar work!", // String (optional)
446 | });
447 | ```
448 | 
449 | ### Reflag feedback API
450 | 
451 | If you are not using the Reflag Browser SDK, you can still submit feedback using the HTTP API.
452 | 
453 | See details in [Feedback HTTP API](https://docs.reflag.com/api/http-api#post-feedback)
454 | 
455 | ## Tracking flag usage
456 | 
457 | The `track` function lets you send events to Reflag to denote flag usage.
458 | By default Reflag expects event names to align with the flag keys, but
459 | you can customize it as you wish.
460 | 
461 | ```ts
462 | reflagClient.track("huddle", { voiceHuddle: true });
463 | ```
464 | 
465 | ## Event listeners
466 | 
467 | Event listeners allow for capturing various events occurring in the `ReflagClient`. This is useful to build integrations with other system or for various debugging purposes. There are 5 kinds of events:
468 | 
469 | - `check`: Your code used `isEnabled` or `config` for a flag
470 | - `flagsUpdated`: Flags were updated. Either because they were loaded as part of initialization or because the user/company updated
471 | - `user`: User information updated (similar to the `identify` call used in tracking terminology)
472 | - `company`: Company information updated (sometimes to the `group` call used in tracking terminology)
473 | - `track`: Track event occurred.
474 | 
475 | Use the `on()` method to add an event listener to respond to certain events. See the API reference for details on each hook.
476 | 
477 | ```ts
478 | import { ReflagClient, CheckEvent, RawFlags } from "@reflag/browser-sdk";
479 | 
480 | const client = new ReflagClient({
481 |   // options
482 | });
483 | 
484 | // or add the hooks after construction:
485 | const unsub = client.on("check", (check: CheckEvent) =>
486 |   console.log(`Check event ${check}`),
487 | );
488 | // use the returned function to unsubscribe, or call `off()` with the same arguments again
489 | unsub();
490 | ```
491 | 
492 | ## Zero PII
493 | 
494 | The Reflag Browser SDK doesn't collect any metadata and HTTP IP addresses are _not_ being stored.
495 | 
496 | For tracking individual users, we recommend using something like database ID as userId, as it's unique and doesn't include any PII (personal identifiable information). If, however, you're using e.g. email address as userId, but prefer not to send any PII to Reflag, you can hash the sensitive data before sending it to Reflag:
497 | 
498 | ```ts
499 | import reflag from "@reflag/browser-sdk";
500 | import { sha256 } from "crypto-hash";
501 | 
502 | reflag.user(await sha256("john_doe"));
503 | ```
504 | 
505 | ## Use of cookies
506 | 
507 | The Reflag Browser SDK uses a couple of cookies to support automated feedback surveys. These cookies are not used for tracking purposes and thus should not need to appear in cookie consent forms.
508 | 
509 | The two cookies are:
510 | 
511 | - `reflag-prompt-${userId}`: store the last automated feedback prompt message ID received to avoid repeating surveys
512 | - `reflag-token-${userId}`: caching a token used to connect to Reflag's live messaging infrastructure that is used to deliver automated feedback surveys in real time.
513 | 
514 | ## TypeScript
515 | 
516 | Types are bundled together with the library and exposed automatically when importing through a package manager.
517 | 
518 | ## Content Security Policy (CSP)
519 | 
520 | If you are running with strict Content Security Policies active on your website, you will need to enable these directives in order to use the SDK:
521 | 
522 | | Directive   | Values                                                             | Reason                                                                                                                                |
523 | | ----------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
524 | | connect-src | [https://front.reflag.com](https://front.reflag.com)               | Basic functionality`                                                                                                                  |
525 | | connect-src | [https://livemessaging.bucket.co](https://livemessaging.bucket.co) | Server sent events for use in automated feedback surveys, which allows for automatically collecting feedback when a user used a flag. |
526 | | style-src   | 'unsafe-inline'                                                    | The feedback UI is styled with inline styles. Not having this directive results unstyled HTML elements.                               |
527 | 
528 | If you are including the Reflag tracking SDK with a `<script>`-tag from `jsdelivr.net` you will also need:
529 | 
530 | | Directive       | Values                                               | Reason                          |
531 | | --------------- | ---------------------------------------------------- | ------------------------------- |
532 | | script-src-elem | [https://cdn.jsdelivr.net](https://cdn.jsdelivr.net) | Loads the Reflag SDK from a CDN |
533 | 
534 | ## License
535 | 
536 | > MIT License
537 | > Copyright (c) 2025 Bucket ApS
538 | 
```

--------------------------------------------------------------------------------
/sdk/@reflag/react-sdk/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | layout:
  3 |   visible: true
  4 | title:
  5 |   visible: true
  6 | description:
  7 |   visible: false
  8 | tableOfContents:
  9 |   visible: true
 10 | outline:
 11 |   visible: true
 12 | pagination:
 13 |   visible: true
 14 | ---
 15 | 
 16 | # Reflag React SDK
 17 | 
 18 | React client side library for [Reflag.com](https://reflag.com)
 19 | 
 20 | Reflag supports flag toggling, tracking flag usage, [requesting feedback](#userequestfeedback) on features, and [remotely configuring flags](#remote-config).
 21 | 
 22 | The Reflag React SDK comes with a [built-in toolbar](https://docs.reflag.com/supported-languages/browser-sdk#toolbar) which appears on `localhost` by default.
 23 | 
 24 | ## Install
 25 | 
 26 | Install via npm:
 27 | 
 28 | ```shell
 29 | npm i @reflag/react-sdk
 30 | ```
 31 | 
 32 | ## Get started
 33 | 
 34 | ### 1. Add the `ReflagProvider` context provider
 35 | 
 36 | Add the `ReflagProvider` context provider to your application:
 37 | 
 38 | **Example:**
 39 | 
 40 | ```tsx
 41 | import { ReflagProvider } from "@reflag/react-sdk";
 42 | 
 43 | <ReflagProvider
 44 |   publishableKey="{YOUR_PUBLISHABLE_KEY}"
 45 |   context={{
 46 |     company: { id: "acme_inc", plan: "pro" },
 47 |     user: { id: "john doe" },
 48 |   }}
 49 |   loadingComponent={<Loading />}
 50 | >
 51 |   {/* children here are shown when loading finishes or immediately if no `loadingComponent` is given */}
 52 | </ReflagProvider>;
 53 | ```
 54 | 
 55 | ### 2. Create a new flag and set up type safety
 56 | 
 57 | Install the Reflag CLI:
 58 | 
 59 | ```shell
 60 | npm i --save-dev @reflag/cli
 61 | ```
 62 | 
 63 | Run `npx reflag new` to create your first flag!
 64 | On the first run, it will sign into Reflag and set up type generation for your project:
 65 | 
 66 | ```shell
 67 | ❯ npx reflag new
 68 | Opened web browser to facilitate login: https://app.reflag.com/api/oauth/cli/authorize
 69 | 
 70 | Welcome to ◪ Reflag!
 71 | 
 72 | ? Where should we generate the types? gen/flags.d.ts
 73 | ? What is the output format? react
 74 | ✔ Configuration created at reflag.config.json.
 75 | 
 76 | Creating flag for app Slick app.
 77 | ? New flag name: Huddle
 78 | ? New flag key: huddle
 79 | ✔ Created flag Huddle with key huddle (https://app.reflag.com/features/huddles)
 80 | ✔ Generated react types in gen/flags.d.ts.
 81 | ```
 82 | 
 83 | > [!Note]
 84 | > By default, types will be generated in `gen/flags.d.ts`.
 85 | > The default `tsconfig.json` file `include`s this file by default, but if your `tsconfig.json` is different, make sure the file is covered in the `include` property.
 86 | 
 87 | ### 3. Use `useFlag(<flagKey>)` to get flag status
 88 | 
 89 | Using the `useFlag` hook from your components lets you toggle flags on/off and track flag usage:
 90 | 
 91 | **Example:**
 92 | 
 93 | ```tsx
 94 | function StartHuddleButton() {
 95 |   const {
 96 |     isEnabled, // boolean indicating if the flag is enabled
 97 |     track, // track usage of the flag
 98 |   } = useFlag("huddle");
 99 | 
100 |   if (!isEnabled) {
101 |     return null;
102 |   }
103 | 
104 |   return <button onClick={track}>Start huddle!</button>;
105 | }
106 | ```
107 | 
108 | `useFlag` can help you do much more. See a full example for `useFlag` [see below](#useflag).
109 | 
110 | ## Setting context
111 | 
112 | Reflag determines which flags are active for a given `user`, `company`, or `other` context.
113 | You can pass these to the `ReflagProvider` using the `context` prop.
114 | 
115 | ### Using the `context` prop
116 | 
117 | ```tsx
118 | <ReflagProvider
119 |   publishableKey={YOUR_PUBLISHABLE_KEY}
120 |   context={{
121 |     user: { id: "user_123", name: "John Doe", email: "john@acme.com" },
122 |     company: { id: "company_123", name: "Acme, Inc" },
123 |     other: { source: "web" },
124 |   }}
125 | >
126 |   <LoadingReflag>
127 |     {/* children here are shown when loading finishes */}
128 |   </LoadingReflag>
129 | </ReflagProvider>
130 | ```
131 | 
132 | ### Legacy individual props (deprecated)
133 | 
134 | For backward compatibility, you can still use individual props, but these are deprecated and will be removed in the next major version:
135 | 
136 | ```tsx
137 | <ReflagProvider
138 |   publishableKey={YOUR_PUBLISHABLE_KEY}
139 |   user={{ id: "user_123", name: "John Doe", email: "john@acme.com" }}
140 |   company={{ id: "company_123", name: "Acme, Inc" }}
141 |   otherContext={{ source: "web" }}
142 | >
143 |   <LoadingReflag>
144 |     {/* children here are shown when loading finishes */}
145 |   </LoadingReflag>
146 | </ReflagProvider>
147 | ```
148 | 
149 | > [!Important]
150 | > The `user`, `company`, and `otherContext` props are deprecated. Use the `context` prop instead, which provides the same functionality in a more structured way.
151 | 
152 | ### Context requirements
153 | 
154 | If you supply `user` or `company` objects, they must include at least the `id` property otherwise they will be ignored in their entirety.
155 | In addition to the `id`, you must also supply anything additional that you want to be able to evaluate flag targeting rules against.
156 | Attributes which are not properties of the `user` or `company` can be supplied using the `other` property.
157 | 
158 | Attributes cannot be nested (multiple levels) and must be either strings, numbers or booleans.
159 | A number of special attributes exist:
160 | 
161 | - `name` -- display name for `user`/`company`,
162 | - `email` -- the email of the user,
163 | - `avatar` -- the URL for `user`/`company` avatar image.
164 | 
165 | To retrieve flags along with their targeting information, use `useFlag(key: string)` hook (described in a section below).
166 | 
167 | Note that accessing `isEnabled` on the object returned by `useFlag()` automatically
168 | generates a `check` event.
169 | 
170 | ## Remote config
171 | 
172 | Remote config is a dynamic and flexible approach to configuring flag behavior outside of your app – without needing to re-deploy it.
173 | 
174 | Similar to `isEnabled`, each flag accessed using the `useFlag()` hook, has a `config` property. This configuration is managed from within Reflag. It is managed similar to the way access to flags is managed, but instead of the
175 | binary `isEnabled` you can have multiple configuration values which are given to different user/companies.
176 | 
177 | ### Get started with Remote config
178 | 
179 | 1. Update your flag definitions:
180 | 
181 | ```typescript
182 | import "@reflag/react-sdk";
183 | 
184 | // Define your flags by extending the `Flags` interface in @reflag/react-sdk
185 | declare module "@reflag/react-sdk" {
186 |   interface Flags {
187 |     huddle: {
188 |       // change from `boolean` to an object which sets
189 |       // a type for the remote config for `questionnaire`
190 |       maxTokens: number;
191 |       model: string;
192 |     };
193 |   }
194 | }
195 | ```
196 | 
197 | ```ts
198 | const {
199 |   isEnabled,
200 |   config: { key, payload },
201 | } = useFlag("huddles");
202 | 
203 | // isEnabled: true,
204 | // key: "gpt-3.5",
205 | // payload: { maxTokens: 10000, model: "gpt-3.5-beta1" }
206 | ```
207 | 
208 | `key` is mandatory for a config, but if a flag has no config or no config value was matched against the context, the `key` will be `undefined`. Make sure to check against this case when trying to use the configuration in your application. `payload` is an optional JSON value for arbitrary configuration needs.
209 | 
210 | Note that, similar to `isEnabled`, accessing `config` on the object returned by `useFlag()` automatically
211 | generates a `check` event.
212 | 
213 | ## Toolbar
214 | 
215 | The Reflag Toolbar is great for toggling flags on/off for yourself to ensure that everything works both when a flag is on and when it's off.
216 | 
217 | <img width="310" height="265" alt="Toolbar" src="https://github.com/user-attachments/assets/61492915-0d30-446d-a163-3eb16d9024b2" />
218 | 
219 | The toolbar will automatically appear on `localhost`. However, it can also be incredibly useful in production. You have full control over when it appears through the `toolbar` configuration option passed to the ReflagProvider.
220 | 
221 | You can pass a simple boolean to force the toolbar to appear/disappear:
222 | 
223 | ```ts
224 | <ReflagProvider
225 |   ...
226 |   // show the toolbar even in production if the user is an internal/admin user
227 |   toolbar={user?.isInternal}
228 |   ...
229 | });
230 | ```
231 | 
232 | ## Server-side rendering and bootstrapping
233 | 
234 | For server-side rendered applications, you can eliminate the initial network request by bootstrapping the client with pre-fetched flag data using the `ReflagBootstrappedProvider`.
235 | 
236 | ### Using `ReflagBootstrappedProvider`
237 | 
238 | The `<ReflagBootstrappedProvider>` component is a specialized version of `ReflagProvider` designed for server-side rendering and preloaded flag scenarios. Instead of fetching flags on initialization, it uses pre-fetched flags, resulting in faster initial page loads and better SSR compatibility.
239 | 
240 | ```tsx
241 | import { useState, useEffect } from "react";
242 | import { BootstrappedFlags } from "@reflag/react-sdk";
243 | 
244 | interface BootstrapData {
245 |   user: User;
246 |   flags: BootstrappedFlags;
247 | }
248 | 
249 | function useBootstrap() {
250 |   const [data, setData] = useState<BootstrapData | null>(null);
251 | 
252 |   useEffect(() => {
253 |     fetch("/bootstrap")
254 |       .then((res) => res.json())
255 |       .then(setData);
256 |   }, []);
257 | 
258 |   return data;
259 | }
260 | 
261 | // Usage in your app
262 | function App() {
263 |   const { user, flags } = useBootstrap();
264 | 
265 |   return (
266 |     <AuthProvider user={user}>
267 |       <ReflagBootstrappedProvider
268 |         publishableKey="your-publishable-key"
269 |         flags={flags}
270 |       >
271 |         <Router />
272 |       </ReflagBootstrappedProvider>
273 |     </AuthProvider>
274 |   );
275 | }
276 | ```
277 | 
278 | ### Server-side endpoint setup
279 | 
280 | Create an endpoint that provides bootstrap data to your client application:
281 | 
282 | ```typescript
283 | // server.js or your Express app
284 | import { ReflagClient as ReflagNodeClient } from "@reflag/node-sdk";
285 | 
286 | const reflagClient = new ReflagNodeClient({
287 |   secretKey: process.env.REFLAG_SECRET_KEY,
288 | });
289 | await reflagClient.initialize();
290 | 
291 | app.get("/bootstrap", (req, res) => {
292 |   const user = getUser(req); // Get user from your auth system
293 |   const company = getCompany(req); // Get company from your auth system
294 | 
295 |   const flags = reflagClient.getFlagsForBootstrap({
296 |     user: { id: "user123", name: "John Doe", email: "john@acme.com" },
297 |     company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
298 |     other: { source: "web" },
299 |   });
300 | 
301 |   res.status(200).json({
302 |     user,
303 |     flags,
304 |   });
305 | });
306 | ```
307 | 
308 | ### Next.js Page Router SSR example
309 | 
310 | For Next.js applications using server-side rendering, you can pre-fetch flags in `getServerSideProps`:
311 | 
312 | ```typescript
313 | // pages/index.tsx
314 | import { GetServerSideProps } from "next";
315 | import { ReflagClient as ReflagNodeClient } from "@reflag/node-sdk";
316 | import { ReflagBootstrappedProvider, BootstrappedFlags, useFlag } from "@reflag/react-sdk";
317 | 
318 | interface PageProps {
319 |   bootstrapData: BootstrappedFlags;
320 | }
321 | 
322 | export const getServerSideProps: GetServerSideProps = async (context) => {
323 |   const serverClient = new ReflagNodeClient({
324 |     secretKey: process.env.REFLAG_SECRET_KEY
325 |   });
326 |   await serverClient.initialize();
327 | 
328 |   const user = await getUserFromSession(context.req);
329 |   const company = await getCompanyFromUser(user);
330 | 
331 |   const bootstrapData = serverClient.getFlagsForBootstrap({
332 |     user: { id: "user123", name: "John Doe", email: "john@acme.com" },
333 |     company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
334 |     other: { page: "homepage" }
335 |   });
336 | 
337 |   return { props: { bootstrapData } };
338 | };
339 | 
340 | export default function HomePage({ bootstrapData }: PageProps) {
341 |   return (
342 |     <ReflagBootstrappedProvider
343 |       publishableKey={process.env.NEXT_PUBLIC_REFLAG_PUBLISHABLE_KEY}
344 |       flags={bootstrapData}
345 |     >
346 |       <HuddleFeature />
347 |     </ReflagBootstrappedProvider>
348 |   );
349 | }
350 | 
351 | function HuddleFeature() {
352 |   const { isEnabled, track, config } = useFlag("huddle");
353 | 
354 |   if (!isEnabled) return null;
355 | 
356 |   return (
357 |     <div>
358 |       <h2>Start a Huddle</h2>
359 |       <p>Max participants: {config.payload?.maxParticipants ?? 10}</p>
360 |       <p>Video quality: {config.payload?.videoQuality ?? "standard"}</p>
361 |       <button onClick={track}>Start Huddle</button>
362 |     </div>
363 |   );
364 | }
365 | ```
366 | 
367 | This approach eliminates loading states and improves performance by avoiding the initial flags API call.
368 | 
369 | ### Next.js App Router example
370 | 
371 | For Next.js applications using the App Router (Next.js 13+), you can pre-fetch flags in Server Components and pass them to client components:
372 | 
373 | ```typescript
374 | // app/layout.tsx (Server Component)
375 | import { ReflagClient as ReflagNodeClient } from "@reflag/node-sdk";
376 | import { ClientProviders } from "./providers";
377 | 
378 | async function getBootstrapData() {
379 |   const serverClient = new ReflagNodeClient({
380 |     secretKey: process.env.REFLAG_SECRET_KEY!
381 |   });
382 |   await serverClient.initialize();
383 | 
384 |   // In a real app, you'd get user/company from your auth system
385 |   const bootstrapData = serverClient.getFlagsForBootstrap({
386 |     user: { id: "user123", name: "John Doe", email: "john@acme.com" },
387 |     company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
388 |     other: { source: "web" }
389 |   });
390 | 
391 |   return bootstrapData;
392 | }
393 | 
394 | export default async function RootLayout({
395 |   children,
396 | }: {
397 |   children: React.ReactNode;
398 | }) {
399 |   const bootstrapData = await getBootstrapData();
400 | 
401 |   return (
402 |     <html lang="en">
403 |       <body>
404 |         <ClientProviders bootstrapData={bootstrapData}>
405 |           {children}
406 |         </ClientProviders>
407 |       </body>
408 |     </html>
409 |   );
410 | }
411 | ```
412 | 
413 | ```typescript
414 | // app/providers.tsx (Client Component)
415 | "use client";
416 | 
417 | import { ReflagBootstrappedProvider, BootstrappedFlags } from "@reflag/react-sdk";
418 | 
419 | interface ClientProvidersProps {
420 |   children: React.ReactNode;
421 |   bootstrapData: BootstrappedFlags;
422 | }
423 | 
424 | export function ClientProviders({ children, bootstrapData }: ClientProvidersProps) {
425 |   return (
426 |     <ReflagBootstrappedProvider
427 |       publishableKey={process.env.NEXT_PUBLIC_REFLAG_PUBLISHABLE_KEY!}
428 |       flags={bootstrapData}
429 |     >
430 |       {children}
431 |     </ReflagBootstrappedProvider>
432 |   );
433 | }
434 | ```
435 | 
436 | ```typescript
437 | // app/page.tsx (Server Component)
438 | import { HuddleFeature } from "./huddle-feature";
439 | 
440 | export default function HomePage() {
441 |   return (
442 |     <main>
443 |       <h1>My App</h1>
444 |       <HuddleFeature />
445 |     </main>
446 |   );
447 | }
448 | ```
449 | 
450 | ```typescript
451 | // app/huddle-feature.tsx (Client Component)
452 | "use client";
453 | 
454 | import { useFlag } from "@reflag/react-sdk";
455 | 
456 | export function HuddleFeature() {
457 |   const { isEnabled, track, config } = useFlag("huddle");
458 | 
459 |   if (!isEnabled) return null;
460 | 
461 |   return (
462 |     <div>
463 |       <h2>Start a Huddle</h2>
464 |       <p>Max participants: {config.payload?.maxParticipants ?? 10}</p>
465 |       <p>Video quality: {config.payload?.videoQuality ?? "standard"}</p>
466 |       <button onClick={track}>Start Huddle</button>
467 |     </div>
468 |   );
469 | }
470 | ```
471 | 
472 | This App Router approach leverages Server Components for server-side flag fetching while using Client Components only where React state and hooks are needed.
473 | 
474 | ## `<ReflagClientProvider>` component
475 | 
476 | The `<ReflagClientProvider>` is a lower-level component that accepts a pre-initialized `ReflagClient` instance. This is useful for advanced use cases where you need full control over client initialization or want to share a client instance across multiple parts of your application.
477 | 
478 | ### Usage
479 | 
480 | ```tsx
481 | import { ReflagClient } from "@reflag/browser-sdk";
482 | import { ReflagClientProvider } from "@reflag/react-sdk";
483 | 
484 | // Initialize the client yourself
485 | const client = new ReflagClient({
486 |   publishableKey: "your-publishable-key",
487 |   user: { id: "user123", name: "John Doe" },
488 |   company: { id: "company456", name: "Acme Inc" },
489 |   // ... other configuration options
490 | });
491 | 
492 | // Initialize the client
493 | await client.initialize();
494 | 
495 | function App() {
496 |   return (
497 |     <ReflagClientProvider client={client} loadingComponent={<Loading />}>
498 |       <Router />
499 |     </ReflagClientProvider>
500 |   );
501 | }
502 | ```
503 | 
504 | ### Props
505 | 
506 | The `ReflagClientProvider` accepts the following props:
507 | 
508 | - `client`: A pre-initialized `ReflagClient` instance
509 | - `loadingComponent`: Optional React component to show while the client is initializing (same as `ReflagProvider`)
510 | 
511 | > [!Note]
512 | > Most applications should use `ReflagProvider` or `ReflagBootstrappedProvider` instead of `ReflagClientProvider`. Only use this component when you need the advanced control it provides.
513 | 
514 | ## `<ReflagProvider>` component
515 | 
516 | The `<ReflagProvider>` initializes the Reflag SDK, fetches flags and starts listening for automated feedback survey events. The component can be configured using a number of props:
517 | 
518 | - `publishableKey` is used to connect the provider to an _environment_ on Reflag. Find your `publishableKey` under [environment settings](https://app.reflag.com/env-current/settings/app-environments) in Reflag,
519 | - `context` (recommended): An object containing `user`, `company`, and `other` properties that make up the evaluation context used to determine if a flag is enabled or not. `company` and `user` contexts are automatically transmitted to Reflag servers so the Reflag app can show you which companies have access to which flags etc.
520 | - `company`, `user` and `other` (deprecated): Individual props for context. These are deprecated in favor of the `context` prop and will be removed in the next major version.
521 |   > [!Note]
522 |   > If you specify `company` and/or `user` they must have at least the `id` property, otherwise they will be ignored in their entirety. You should also supply anything additional you want to be able to evaluate flag targeting against,
523 | - `fallbackFlags`: A list of strings which specify which flags to consider enabled if the SDK is unable to fetch flags. Can be provided in two formats:
524 | 
525 |   ```ts
526 |   // Simple array of flag keys
527 |   fallbackFlags={["flag1", "flag2"]}
528 | 
529 |   // Or with configuration overrides
530 |   fallbackFlags: {
531 |       "flag1": true,  // just enable the flag
532 |       "flag2": {      // enable with configuration
533 |         key: "variant-a",
534 |         payload: {
535 |           limit: 100,
536 |           mode: "test"
537 |         }
538 |       }
539 |   }
540 |   ```
541 | 
542 | - `timeoutMs`: Timeout in milliseconds when fetching flags from the server.
543 | - `staleWhileRevalidate`: If set to `true`, stale flags will be returned while refetching flags in the background.
544 | - `expireTimeMs`: If set, flags will be cached between page loads for this duration (in milliseconds).
545 | - `staleTimeMs`: Maximum time (in milliseconds) that stale flags will be returned if `staleWhileRevalidate` is true and new flags cannot be fetched.
546 | - `offline`: Provide this option when testing or in local development environments to avoid contacting Reflag servers.
547 | - `loadingComponent` lets you specify an React component to be rendered instead of the children while the Reflag provider is initializing. If you want more control over loading screens, `useFlag()` and `useIsLoading` returns `isLoading` which you can use to customize the loading experience.
548 | - `enableTracking`: Set to `false` to stop sending tracking events and user/company updates to Reflag. Useful when you're impersonating a user (defaults to `true`),
549 | - `apiBaseUrl`: Optional base URL for the Reflag API. Use this to override the default API endpoint,
550 | - `appBaseUrl`: Optional base URL for the Reflag application. Use this to override the default app URL,
551 | - `sseBaseUrl`: Optional base URL for Server-Sent Events. Use this to override the default SSE endpoint,
552 | - `debug`: Set to `true` to enable debug logging to the console,
553 | - `toolbar`: Optional [configuration](https://docs.reflag.com/supported-languages/browser-sdk/globals#toolbaroptions) for the Reflag toolbar,
554 | - `feedback`: Optional configuration for feedback collection
555 | 
556 | ## `<ReflagBootstrappedProvider>` component
557 | 
558 | The `<ReflagBootstrappedProvider>` is a specialized version of the `ReflagProvider` that uses pre-fetched flag data instead of making network requests during initialization. This is ideal for server-side rendering scenarios.
559 | 
560 | The component accepts the following props:
561 | 
562 | - `flags`: Pre-fetched flags data of type `BootstrappedFlags` obtained from the Node SDK's `getFlagsForBootstrap()` method. This contains both the context (user, company, other) and the flags data.
563 | - All other props available in [`ReflagProvider`](#reflagprovider-component) are supported except `context`, `user`, `company`, and `other` (which are extracted from `flags.context`).
564 | 
565 | **Example:**
566 | 
567 | ```tsx
568 | import {
569 |   ReflagBootstrappedProvider,
570 |   BootstrappedFlags,
571 | } from "@reflag/react-sdk";
572 | 
573 | interface AppProps {
574 |   bootstrapData: BootstrappedFlags;
575 | }
576 | 
577 | function App({ bootstrapData }: AppProps) {
578 |   return (
579 |     <ReflagBootstrappedProvider
580 |       publishableKey="your-publishable-key"
581 |       flags={bootstrapData}
582 |       loadingComponent={<Loading />}
583 |       debug={process.env.NODE_ENV === "development"}
584 |     >
585 |       <Router />
586 |     </ReflagBootstrappedProvider>
587 |   );
588 | }
589 | ```
590 | 
591 | > [!Note]
592 | > When using `ReflagBootstrappedProvider`, the context (user, company, and other) is extracted from the `flags.context` property and doesn't need to be passed separately.
593 | 
594 | ## Hooks
595 | 
596 | ### `useFlag()`
597 | 
598 | Returns the state of a given flag for the current context. The hook provides type-safe access to flags and their configurations.
599 | 
600 | ```tsx
601 | import { useFlag } from "@reflag/react-sdk";
602 | import { Loading } from "./Loading";
603 | 
604 | function StartHuddleButton() {
605 |   const {
606 |     isLoading, // true while flags are being loaded
607 |     isEnabled, // boolean indicating if the flag is enabled
608 |     config: {
609 |       // flag configuration
610 |       key, // string identifier for the config variant
611 |       payload, // type-safe configuration object
612 |     },
613 |     track, // function to track flag usage
614 |     requestFeedback, // function to request feedback for this flag
615 |   } = useFlag("huddle");
616 | 
617 |   if (isLoading) {
618 |     return <Loading />;
619 |   }
620 | 
621 |   if (!isEnabled) {
622 |     return null;
623 |   }
624 | 
625 |   return (
626 |     <>
627 |       <button onClick={track}>Start huddle!</button>
628 |       <button
629 |         onClick={(e) =>
630 |           requestFeedback({
631 |             title: payload?.question ?? "How do you like the Huddles feature?",
632 |             position: {
633 |               type: "POPOVER",
634 |               anchor: e.currentTarget as HTMLElement,
635 |             },
636 |           })
637 |         }
638 |       >
639 |         Give feedback!
640 |       </button>
641 |     </>
642 |   );
643 | }
644 | ```
645 | 
646 | ### `useTrack()`
647 | 
648 | `useTrack()` lets you send custom events to Reflag. Use this whenever a user _uses_ a feature. These events can be used to analyze feature usage in Reflag.
649 | 
650 | ```tsx
651 | import { useTrack } from "@reflag/react-sdk";
652 | 
653 | function StartHuddle() {
654 |   const { track } = useTrack();
655 |   <div>
656 |     <button onClick={() => track("Huddle Started", { huddleType: "voice" })}>
657 |       Start voice huddle!
658 |     </button>
659 |   </div>;
660 | }
661 | ```
662 | 
663 | ### `useRequestFeedback()`
664 | 
665 | `useRequestFeedback()` returns a function that lets you open up a dialog to ask for feedback on a specific feature. This is useful for collecting targeted feedback about specific features as part of roll out. See [Automated Feedback Surveys](https://docs.reflag.com/product-handbook/live-satisfaction) for how to do this automatically, without code.
666 | 
667 | When using the `useRequestFeedback` you must pass the flag key to `requestFeedback`.
668 | The example below shows how to use `position` to ensure the popover appears next to the "Give feedback!" button.
669 | 
670 | ```tsx
671 | import { useRequestFeedback } from "@reflag/react-sdk";
672 | 
673 | function FeedbackButton() {
674 |   const requestFeedback = useRequestFeedback();
675 |   return (
676 |     <button
677 |       onClick={(e) =>
678 |         requestFeedback({
679 |           flagKey: "huddle-flag",
680 |           title: "How satisfied are you with file uploads?",
681 |           position: {
682 |             type: "POPOVER",
683 |             anchor: e.currentTarget as HTMLElement,
684 |           },
685 |           // Optional custom styling
686 |           style: {
687 |             theme: "light",
688 |             primaryColor: "#007AFF",
689 |           },
690 |         })
691 |       }
692 |     >
693 |       Give feedback!
694 |     </button>
695 |   );
696 | }
697 | ```
698 | 
699 | See the [Feedback Documentation](https://github.com/reflagcom/javascript/blob/main/packages/browser-sdk/FEEDBACK.md#manual-feedback-collection) for more information on `requestFeedback` options.
700 | 
701 | ### `useSendFeedback()`
702 | 
703 | Returns a function that lets you send feedback to Reflag. This is useful if you've manually collected feedback through your own UI and want to send it to Reflag.
704 | 
705 | ```tsx
706 | import { useSendFeedback } from "@reflag/react-sdk";
707 | 
708 | function CustomFeedbackForm() {
709 |   const sendFeedback = useSendFeedback();
710 | 
711 |   const handleSubmit = async (data: FormData) => {
712 |     await sendFeedback({
713 |       flagKey: "reflag-flag-key",
714 |       score: parseInt(data.get("score") as string),
715 |       comment: data.get("comment") as string,
716 |     });
717 |   };
718 | 
719 |   return <form onSubmit={handleSubmit}>...</form>;
720 | }
721 | ```
722 | 
723 | ### `useUpdateUser()`, `useUpdateCompany()` and `useUpdateOtherContext()`
724 | 
725 | These hooks return functions that let you update the attributes for the currently set user, company, or other context. Updates to user/company are stored remotely and affect flag targeting, while "other" context updates only affect the current session.
726 | 
727 | ```tsx
728 | import {
729 |   useUpdateUser,
730 |   useUpdateCompany,
731 |   useUpdateOtherContext,
732 | } from "@reflag/react-sdk";
733 | 
734 | function FlagOptIn() {
735 |   const updateUser = useUpdateUser();
736 |   const updateCompany = useUpdateCompany();
737 |   const updateOtherContext = useUpdateOtherContext();
738 | 
739 |   const handleUserUpdate = async () => {
740 |     await updateUser({
741 |       role: "admin",
742 |       betaFlags: "enabled",
743 |     });
744 |   };
745 | 
746 |   const handleCompanyUpdate = async () => {
747 |     await updateCompany({
748 |       plan: "enterprise",
749 |       employees: 500,
750 |     });
751 |   };
752 | 
753 |   const handleContextUpdate = async () => {
754 |     await updateOtherContext({
755 |       currentWorkspace: "workspace-123",
756 |       theme: "dark",
757 |     });
758 |   };
759 | 
760 |   return (
761 |     <div>
762 |       <button onClick={handleUserUpdate}>Update User</button>
763 |       <button onClick={handleCompanyUpdate}>Update Company</button>
764 |       <button onClick={handleContextUpdate}>Update Context</button>
765 |     </div>
766 |   );
767 | }
768 | ```
769 | 
770 | ### `useClient()`
771 | 
772 | Returns the `ReflagClient` used by the `ReflagProvider`. The client offers more functionality that
773 | is not directly accessible thorough the other hooks.
774 | 
775 | ```tsx
776 | import { useClient } from "@reflag/react-sdk";
777 | 
778 | function LoggingWrapper({ children }: { children: ReactNode }) {
779 |   const client = useClient();
780 | 
781 |   console.log(client.getContext());
782 | 
783 |   return children;
784 | }
785 | ```
786 | 
787 | ### `useIsLoading()`
788 | 
789 | Returns the loading state of the flags in the `ReflagClient`.
790 | Initially, the value will be `true` if no bootstrap flags have been provided and the client has not be initialized.
791 | 
792 | ```tsx
793 | import { useIsLoading } from "@reflag/react-sdk";
794 | import { Spinner } from "./Spinner";
795 | 
796 | function LoadingWrapper({ children }: { children: ReactNode }) {
797 |   const isLoading = useIsLoading();
798 | 
799 |   if (isLoading) {
800 |     return <Spinner />;
801 |   }
802 | 
803 |   return children;
804 | }
805 | ```
806 | 
807 | ### `useOnEvent()`
808 | 
809 | Attach a callback handler to client events to act on changes. It automatically disposes itself on unmount.
810 | 
811 | ```tsx
812 | import { useOnEvent } from "@reflag/react-sdk";
813 | 
814 | function LoggingWrapper({ children }: { children: ReactNode }) {
815 |   useOnEvent("flagsUpdated", (newFlags) => {
816 |     console.log(newFlags);
817 |   });
818 | 
819 |   return children;
820 | }
821 | ```
822 | 
823 | ## Migrating from Bucket SDK
824 | 
825 | If you have been using the Bucket SDKs, the following list will help you migrate to Reflag SDK:
826 | 
827 | - `Bucket*` classes, and types have been renamed to `Reflag*` (e.g. `BucketClient` is now `ReflagClient`)
828 | - `Feature*` classes, and types have been renamed to `Flag*` (e.g. `Feature` is now `Flag`, `RawFeatures` is now `RawFlags`)
829 | - When using strongly-typed flags, the new `Flags` interface replaced `Features` interface
830 | - All methods that contained `feature` in the name have been renamed to use the `flag` terminology (e.g. `getFeature` is `getFlag`)
831 | - The `fallbackFeatures` property in client constructor and configuration files has been renamed to `fallbackFlags`
832 | - `featureKey` has been renamed to `flagKey` in all methods that accepts that argument
833 | - The SDKs will not emit `evaluate` and `evaluate-config` events anymore
834 | - The new cookies that are stored in the client's browser are now `reflag-*` prefixed instead of `bucket-*`
835 | - The `featuresUpdated` hook has been renamed to `flagsUpdated`
836 | - The `checkIsEnabled` and `checkConfig` hooks have been removed, use `check` from now on
837 | 
838 | To ease in transition to Reflag SDK, some of the old methods have been preserved as aliases to the new methods:
839 | 
840 | - `getFeature` method is an alias for `getFlag`
841 | - `getFeatures` method is an alias for `getFlags`
842 | - `useFeature` method is an alias for `useFlag`
843 | - `featuresUpdated` hook is an alias for `flagsUpdated`
844 | 
845 | If you are running with strict Content Security Policies active on your website, you will need change them as follows:
846 | 
847 | - `connect-src https://front.bucket.co` to `connect-src https://front.reflag.com`
848 | 
849 | ## Content Security Policy (CSP)
850 | 
851 | See [CSP](https://github.com/reflagcom/javascript/blob/main/packages/browser-sdk/README.md#content-security-policy-csp) for info on using Reflag React SDK with CSP
852 | 
853 | ## License
854 | 
855 | MIT License
856 | 
857 | Copyright (c) 2025 Bucket ApS
858 | 
```

