diff --git a/.eslintignore b/.eslintignore index 8febed237..20cf0700e 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,4 +3,4 @@ dist *.js # Auto-generated disclaimer causes an eslint parsing error -docs/reference/technologies/**/*.mdx \ No newline at end of file +docs/reference/sdks/**/*.mdx \ No newline at end of file diff --git a/.gitignore b/.gitignore index a4423338d..999983f46 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ yarn-error.log* .idea .wireit .eslintcache +.cursor diff --git a/.markdownlint-cli2.yaml b/.markdownlint-cli2.yaml index 7f922b42c..0d1b1e2ce 100644 --- a/.markdownlint-cli2.yaml +++ b/.markdownlint-cli2.yaml @@ -1,4 +1,3 @@ - config: default: true @@ -33,6 +32,8 @@ ignores: - external-content - docs/specification # Fetched from each SDK's README.md - - docs/reference/technologies/@(client|server)/**/*.mdx + - docs/reference/sdks/@(client|server)/**/*.mdx + # Fetched from other technology repos + - docs/reference/other-technologies/*.mdx fix: true diff --git a/LICENSE-CODE b/LICENSE-CODE index 261eeb9e9..96b3dc8fc 100644 --- a/LICENSE-CODE +++ b/LICENSE-CODE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright OpenFeature Maintainers Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/blog/2022-10-21-hardening-and-1-0-sdks.md b/blog/2022-10-21-hardening-and-1-0-sdks.md index 8eb37bb59..53aaef6e9 100644 --- a/blog/2022-10-21-hardening-and-1-0-sdks.md +++ b/blog/2022-10-21-hardening-and-1-0-sdks.md @@ -22,7 +22,7 @@ The release includes stable versions the following features: The specification documents associated with these features have been marked as `hardening`, meaning breaking changes are no longer allowed and usage of these features are encouraged in production environments. The release of these SDKs and the stabilization of the specification represent a culmination of efforts by a dedicated group of vendors, practitioners and subject matter experts. -Providers are [already available](https://openfeature.dev/docs/reference/technologies/) for major vendors and popular community projects. +Providers are [already available](https://openfeature.dev/docs/reference/sdks/) for major vendors and popular community projects. It's our hope that the efforts to stabilize the OpenFeature specification and SDKs will lead to more adoption of both OpenFeature and feature flagging in general, and promote a vibrant ecosystem around this increasingly important development pattern. In addition to those mentioned above, experimental features available in the 1.0 SDKs include: @@ -33,7 +33,9 @@ In addition to those mentioned above, experimental features available in the 1.0 ## What's next? -Our goal in the upcoming months will be to harden our existing experimental features. Additionally, we'll work to develop and standardize new capabilities, including: client-side feature flagging, improved cloud native tooling, and implicit transaction-scoped data propagation of contextual attributes. +Our goal in the upcoming months will be to harden our existing experimental features. +Additionally, we'll work to develop and standardize new capabilities, including: client-side feature flagging, improved cloud native tooling, and implicit transaction-scoped data propagation of contextual attributes. Furthermore, we're working on SDKs for additional languages, including [PHP](https://github.com/open-feature/php-sdk), [Python](https://github.com/open-feature/python-sdk), and [Ruby](https://github.com/open-feature/ruby-sdk). -If you're interested in contributing or learning more about OpenFeature, please join our expanding and friendly community. Visit our [GitHub](https://github.com/open-feature), join the [OpenFeature slack channel](https://cloud-native.slack.com/archives/C0344AANLA1) on the CNCF Slack instance, or hop into our [bi-weekly community meeting](https://github.com/open-feature/community#meetings-and-events). +If you're interested in contributing or learning more about OpenFeature, please join our expanding and friendly community. +Visit our [GitHub](https://github.com/open-feature), join the [OpenFeature slack channel](https://cloud-native.slack.com/archives/C0344AANLA1) on the CNCF Slack instance, or hop into our [bi-weekly community meeting](https://github.com/open-feature/community#meetings-and-events). diff --git a/blog/2023-03-27-feature-flags-if-statements.md b/blog/2023-03-27-feature-flags-if-statements.md index 5f48b2980..201362da6 100644 --- a/blog/2023-03-27-feature-flags-if-statements.md +++ b/blog/2023-03-27-feature-flags-if-statements.md @@ -11,7 +11,8 @@ draft: false Most feature flag explainers begin by explaining that feature flags are equivalent to environment variables. -While that’s true (to a point), feature flags wouldn’t be as versatile or as popular as they are, if that’s all they were. Indeed, you wouldn’t need a feature flag – you could easily achieve the same thing with an environment variable. +While that’s true (to a point), feature flags wouldn’t be as versatile or as popular as they are, if that’s all they were. +Indeed, you wouldn’t need a feature flag – you could easily achieve the same thing with an environment variable. @@ -26,28 +27,37 @@ if isPremiumMember { return v1 } ``` + Now try modeling this in code: + - If user is premium and located in Europe = v2 (purple) - If user is premium and located in the US = v3 (red) - If user is premium and located in Australia = v4 (orange) - Everyone else gets v1 (green) -That’s 2 variables. Imagine how many variations a real system has. Now imagine trying to update these conditions in real time, without a redeployment. +That’s 2 variables. +Imagine how many variations a real system has. +Now imagine trying to update these conditions in real time, without a redeployment. The real power of feature flags: -- Simple or complex: Flag rules can be as simple or as complex as you wish. This makes getting started easy with plenty of room to grow and expand. -- Separation of concerns: Feature flags allow a deployment without a release. All new features are placed behind flags and those flags are disabled during deployment. +- Simple or complex: Flag rules can be as simple or as complex as you wish. + This makes getting started easy with plenty of room to grow and expand. +- Separation of concerns: Feature flags allow a deployment without a release. + All new features are placed behind flags and those flags are disabled during deployment. - Shortcut to continuous delivery: If you can deploy anything at any time with zero risk, why not do it? - Separation of responsibilities: Product managers take responsibility for feature flags, leaving DevOps teams to deal with their area of responsibility. ## So, are Feature Flags if Statements? -No, feature flagging is so much more powerful and dynamic than environment variables or if statements. But if you’re already using if statements, you already have enough knowledge to take your environment variables and if statements to the next level with feature flags. + +No, feature flagging is so much more powerful and dynamic than environment variables or if statements. +But if you’re already using if statements, you already have enough knowledge to take your environment variables and if statements to the next level with feature flags. If you’re stuck on the environment variable + if statement metaphor, feature flags are a very flexible if statement that you can **target**, **update**, **toggle** and **gain observability over**, in **real time** without a **re-deployment**. ## Where Do I Start? + Start with the OpenFeature hands-on tutorials. These tutorials are provided by Killercoda, a third-party in-browser learning platform. @@ -55,18 +65,22 @@ These tutorials are provided by Killercoda, a third-party in-browser learning pl All tutorials are free to use and the [tutorial source code is open](https://github.com/open-feature/killercoda). ### 1: OpenFeature Demo + Never encountered feature flags? This is the 30,000ft view showing the power and versatility of feature flags. [Start here](https://killercoda.com/open-feature/scenario/openfeature-demo). ### 2: An Open Source Feature Flag Backend + Decided to adopt feature flags? You will need a flag "backend" evaluation engine. -Any open source tool or vendor can support OpenFeature and many do. Check the [technologies section](https://openfeature.dev/docs/reference/technologies/) to see what tools and vendors are supported in your language. +Any open source tool or vendor can support OpenFeature and many do. +Check the [technologies section](https://openfeature.dev/docs/reference/sdks/) to see what tools and vendors are supported in your language. -If you don't already use a flag evaluation system, flagd is a good place to start without having to code your own backend solution. Try the [flagd demo on killercoda](https://killercoda.com/open-feature/scenario/flagd-demo). +If you don't already use a flag evaluation system, flagd is a good place to start without having to code your own backend solution. +Try the [flagd demo on killercoda](https://killercoda.com/open-feature/scenario/flagd-demo). ### 3. Instrument Your Application @@ -77,8 +91,10 @@ Your application must now be modified to interact with your chosen flag evaluati The [Five minutes to feature flags](https://killercoda.com/open-feature/scenario/five-minutes-to-feature-flags) tutorial walks through how to do this. ### 4: Feature Flags on Kubernetes? + Are you Kubernetes-native and want to manage and use feature flags entirely on Kubernetes? Any open source or vendor tool which offers OpenFeature compliant k8s feature flagging will work. -The [Operator tutorial](https://killercoda.com/open-feature/scenario/openfeature-operator-demo) shows one option, using flagd. Flagd leverages Custom Resources to manage feature flags via GitOps and make feature flags available to your pods via annotations. \ No newline at end of file +The [Operator tutorial](https://killercoda.com/open-feature/scenario/openfeature-operator-demo) shows one option, using flagd. +Flagd leverages Custom Resources to manage feature flags via GitOps and make feature flags available to your pods via annotations. diff --git a/blog/2023-12-19-december-update-blog.md b/blog/2023-12-19-december-update-blog.md index ad0149305..b68388957 100644 --- a/blog/2023-12-19-december-update-blog.md +++ b/blog/2023-12-19-december-update-blog.md @@ -10,9 +10,11 @@ draft: false ## December 2023 Update -Hello OpenFeature Community 👋 +Hello OpenFeature Community 👋 -Happy holidays and a very happy new year in the coming weeks! There’s a lot happening as we wind down the year, so keep reading! As always, we thank you for your continued support and contributions and look forward to an exciting new year in 2024! +Happy holidays and a very happy new year in the coming weeks! +There’s a lot happening as we wind down the year, so keep reading! +As always, we thank you for your continued support and contributions and look forward to an exciting new year in 2024! @@ -20,79 +22,94 @@ Happy holidays and a very happy new year in the coming weeks! There’s a lot ha -🤩 We are ecstatic to announce that the Cloud Native Computing Foundation’s Technical Oversight Committee has promoted OpenFeature to Incubating project status! 🎉 Many thanks to our wonderful community of maintainers, contributors, and users! 🙏 ✨ +🤩 We are ecstatic to announce that the Cloud Native Computing Foundation’s Technical Oversight Committee has promoted OpenFeature to Incubating project status! 🎉 Many thanks to our wonderful community of maintainers, contributors, and users! 🙏 ✨ 📰 [Read more about incubation and the future of OpenFeature here.](https://www.cncf.io/?p=98784) ### New & Notable -#### Governance Committee Elections! +#### Governance Committee Elections -We’re happy to announce the OpenFeature Governance Committee Elections are now open! 🗳️ At this time we’re inviting all [OpenFeature GitHub Org Members, Approvers, and Maintainers](https://github.com/orgs/open-feature/people) to review the list of [candidates](https://github.com/open-feature/community/blob/main/Elections/2023/Candidates.md), then cast your vote for 4 current committee members (with 1 year term) and 3 new candidates (via [helios](https://vote.heliosvoting.org/) using your GitHub account). +We’re happy to announce the OpenFeature Governance Committee Elections are now open! 🗳️ At this time we’re inviting all [OpenFeature GitHub Org Members, Approvers, and Maintainers](https://github.com/orgs/open-feature/people) to review the list of [candidates](https://github.com/open-feature/community/blob/main/Elections/2023/Candidates.md), then cast your vote for 4 current committee members (with 1 year term) and 3 new candidates (via [helios](https://vote.heliosvoting.org/) using your GitHub account). + +Voting period is open through January 31, 2024. +For more information on the election process, please see the following: -Voting period is open through January 31, 2024. For more information on the election process, please see the following: * [2023 OpenFeature GC Elections GitHub Issue](https://github.com/open-feature/community/issues/262) -* [2023 OpenFeature GC Election Process](https://github.com/open-feature/community/blob/main/Elections/2023/Election-Guidelines.md) +* [2023 OpenFeature GC Election Process](https://github.com/open-feature/community/blob/main/Elections/2023/Election-Guidelines.md) * [2023 OpenFeature GC Candidates](https://github.com/open-feature/community/blob/main/Elections/2023/Candidates.md) -#### SDK Compatibility Overview +#### SDK Compatibility Overview -You can now see the status and supported features of the OpenFeature SDKs in a simplified visual matrix for both Server-side and Client-side SDKs. Check it out [here](https://openfeature.dev/docs/reference/technologies/sdk-compatibility). +You can now see the status and supported features of the OpenFeature SDKs in a simplified visual matrix for both Server-side and Client-side SDKs. +Check it out [here](https://openfeature.dev/docs/reference/sdks/sdk-compatibility). #### OpenFeature Remote Evaluation Protocol -The OpenFeature Remote Evaluation Protocol is an initiative that focuses on defining a vendor-agnostic mechanism for performing flag evaluation over a network. For more information, please refer to the [meeting notes](https://docs.google.com/document/d/1pp6t2giTcdEdVAri_2B1Z6Mv8mHhvtZT1AmkPV9K7xQ/edit#bookmark=kix.koqus874gx4n) from the initial Special Interest Group (SIG) meeting, or the [GitHub Discussion](https://github.com/orgs/open-feature/discussions/249).  +The OpenFeature Remote Evaluation Protocol is an initiative that focuses on defining a vendor-agnostic mechanism for performing flag evaluation over a network. +For more information, please refer to the [meeting notes](https://docs.google.com/document/d/1pp6t2giTcdEdVAri_2B1Z6Mv8mHhvtZT1AmkPV9K7xQ/edit#bookmark=kix.koqus874gx4n) from the initial Special Interest Group (SIG) meeting, or the [GitHub Discussion](https://github.com/orgs/open-feature/discussions/249). -##### Survey  +##### Survey -If you are familiar with the architecture of a particular feature flagging solution [please participate in this survey](https://forms.gle/Gz2AaMdMaAXgFZB57). It aims to understand what's important to existing projects and vendors so that we can incorporate the feedback into the OpenFeature specification.  +If you are familiar with the architecture of a particular feature flagging solution [please participate in this survey](https://forms.gle/Gz2AaMdMaAXgFZB57). +It aims to understand what's important to existing projects and vendors so that we can incorporate the feedback into the OpenFeature specification. ### Contributing -We welcome contributors of all kinds! Please visit us on [GitHub](https://github.com/open-feature), check out our [Contributing Guidelines](https://github.com/open-feature/.github/blob/main/CONTRIBUTING.md) and [Contributor Ladder](https://github.com/open-feature/community/blob/main/CONTRIBUTOR_LADDER.md), and if you're ready to dive-in here's a collection of [Good First Issues](https://github.com/issues?q=is%3Aopen+is%3Aissue+archived%3Afalse+label%3A%22good+first+issue%22+user%3Aopen-feature+)! +We welcome contributors of all kinds! +Please visit us on [GitHub](https://github.com/open-feature), check out our [Contributing Guidelines](https://github.com/open-feature/.github/blob/main/CONTRIBUTING.md) and [Contributor Ladder](https://github.com/open-feature/community/blob/main/CONTRIBUTOR_LADDER.md), and if you're ready to dive-in here's a collection of [Good First Issues](https://github.com/issues?q=is%3Aopen+is%3Aissue+archived%3Afalse+label%3A%22good+first+issue%22+user%3Aopen-feature+)! #### Roadmap 🛣️ -If you'd like to see what we're working on and what we've got planned, please check out the [OpenFeature Roadmap here](https://github.com/orgs/open-feature/projects/1/views/1).  + +If you'd like to see what we're working on and what we've got planned, please check out the [OpenFeature Roadmap here](https://github.com/orgs/open-feature/projects/1/views/1). #### Shout Outs 👏 -🥇 We’d like to make a special shout out and huge thank you to the newest member of our [Technical Committee](https://openfeature.dev/community/tech-committee-charter/), Lukas Reining! 🎉    -Lukas is an IT Consultant at [Codecentric](https://www.codecentric.de/datenschutzerklaerung) and is also a Maintainer of the [OpenFeature JavaScript SDK](https://github.com/open-feature/js-sdk/tree/main). His interest in OpenFeature began when his team was evaluating feature flagging solutions for one of their projects. OpenFeature helped them try out different solutions and even shift later.   +🥇 We’d like to make a special shout out and huge thank you to the newest member of our [Technical Committee](https://openfeature.dev/community/tech-committee-charter/), Lukas Reining! 🎉 + +Lukas is an IT Consultant at [Codecentric](https://www.codecentric.de/datenschutzerklaerung) and is also a Maintainer of the [OpenFeature JavaScript SDK](https://github.com/open-feature/js-sdk/tree/main). +His interest in OpenFeature began when his team was evaluating feature flagging solutions for one of their projects. +OpenFeature helped them try out different solutions and even shift later.   “Feature flagging is a great technique for teams and organizations, and OpenFeature has the potential to help get the most value out of this.”   You can find Lukas on [GitHub](https://github.com/lukas-reining) and [Twitter](https://twitter.com/luku1806).   -#### Join the OpenFeature Org on GitHub! +#### Join the OpenFeature Org on GitHub -If you’re a contributing member, but haven’t joined the [OpenFeature Project Org](https://github.com/open-feature) yet, we’d like to invite you to do so (this also means you can vote in the GC elections)! Here’s how: +If you’re a contributing member, but haven’t joined the [OpenFeature Project Org](https://github.com/open-feature) yet, we’d like to invite you to do so (this also means you can vote in the GC elections)! +Here’s how: -* Please read through our [Contributor Ladder](https://github.com/open-feature/community/blob/main/CONTRIBUTOR_LADDER.md)  -* Open an issue in the [Community Repo](https://github.com/open-feature/community), using this [Organization Membership Request Template](https://github.com/open-feature/community/issues/new?assignees=%40open-feature%2Fmaintainers&labels=area%2Fgithub-membership&projects=&template=membership.md&title=REQUEST%3A+New+membership+for+%3Cyour-GH-handle%3E).  +* Please read through our [Contributor Ladder](https://github.com/open-feature/community/blob/main/CONTRIBUTOR_LADDER.md) +* Open an issue in the [Community Repo](https://github.com/open-feature/community), using this [Organization Membership Request Template](https://github.com/open-feature/community/issues/new?assignees=%40open-feature%2Fmaintainers&labels=area%2Fgithub-membership&projects=&template=membership.md&title=REQUEST%3A+New+membership+for+%3Cyour-GH-handle%3E). ### Upcoming Events & Recent Talks #### Events 🗓️ -Join us on the [CNCF OpenFeature Community Chapter](https://community.cncf.io/openfeature/). This is where we will list all our upcoming events & meetings with details on how to join. Upcoming meetings:  +Join us on the [CNCF OpenFeature Community Chapter](https://community.cncf.io/openfeature/). +This is where we will list all our upcoming events & meetings with details on how to join. +Upcoming meetings: -* [December 21 @ 10am ET / 4pm CET – OpenFeature Community Meeting](https://community.cncf.io/events/details/cncf-openfeature-presents-openfeature-community-meeting-2023-12-21/)  +* [December 21 @ 10am ET / 4pm CET – OpenFeature Community Meeting](https://community.cncf.io/events/details/cncf-openfeature-presents-openfeature-community-meeting-2023-12-21/) * [January 4, 2024 @ 10am ET / 4pm CET – OpenFeature Community Meeting](https://community.cncf.io/events/details/cncf-openfeature-presents-openfeature-community-meeting-2024-01-04/)   -* [January 18, 2024 @ 10am ET / 4pm CET – OpenFeature Community Meeting](https://community.cncf.io/events/details/cncf-openfeature-presents-openfeature-community-meeting-2024-01-18/)  +* [January 18, 2024 @ 10am ET / 4pm CET – OpenFeature Community Meeting](https://community.cncf.io/events/details/cncf-openfeature-presents-openfeature-community-meeting-2024-01-18/) #### Recent Talks 📺 * [Cloud Native Islamabad Workshop: A Guided Tour of OpenFeature by Saim Safdar & Adam Gardner](https://www.youtube.com/live/C19YGf0t-2g?feature=shared) * [KubeCon Europe 2023: Building a Kubernetes Experimentation Platform with OpenFeature; Enabling Organizations to Put Theory into Practice by Alex Jones](https://youtu.be/hlvoJhMx2HU?feature=shared) -* [CNCF on-demand Webinar: An Introduction to Feature Flagging & OpenFeature by Adam Gardner](https://youtu.be/LTvTr6kp53Y?feature=shared)  -* [St Louis Go Meetup: OpenFeature: Revolutionizing Feature Management by James Carr](https://www.youtube.com/live/Mhd2VEul-To?feature=shared&t=281)  -* [Swiss CloudNative Day: OpenFeature - Managing Feature Flags by Robin Wyss & Nicola Roten](https://youtu.be/EJI3ODhh8Y8?feature=shared)  +* [CNCF on-demand Webinar: An Introduction to Feature Flagging & OpenFeature by Adam Gardner](https://youtu.be/LTvTr6kp53Y?feature=shared) +* [St Louis Go Meetup: OpenFeature: Revolutionizing Feature Management by James Carr](https://www.youtube.com/live/Mhd2VEul-To?feature=shared&t=281) +* [Swiss CloudNative Day: OpenFeature - Managing Feature Flags by Robin Wyss & Nicola Roten](https://youtu.be/EJI3ODhh8Y8?feature=shared) * [AppDeveloperCon 2023: Build Progressive Delivery and Safety Into Your Apps with Feature Flags by Adam Gardner](https://youtu.be/D9kzXExhLfY?feature=shared) ### 💬 Connect with Us! 🤝 -[Subscribe to our low traffic CNCF Mailing List](https://lists.cncf.io/g/cncf-openfeature-project) to stay up to date on project announcements, events, and more!  +[Subscribe to our low traffic CNCF Mailing List](https://lists.cncf.io/g/cncf-openfeature-project) to stay up to date on project announcements, events, and more! -💬 Chat with us on [CNCF Slack](https://cloud-native.slack.com/) in the [#openfeature channel](https://cloud-native.slack.com/archives/C0344AANLA1). If you are not part of the CNCF slack workspace already, you can [get an invite here](https://communityinviter.com/apps/cloud-native/cncf). You can also follow us on all the socials: [Twitter](http://twitter.com/OpenFeature) | [LinkedIn](https://www.linkedin.com/company/openfeature/) | [YouTube](https://www.youtube.com/channel/UCXSFt-dT2HORGXz1-ksxtxw) +💬 Chat with us on [CNCF Slack](https://cloud-native.slack.com/) in the [#openfeature channel](https://cloud-native.slack.com/archives/C0344AANLA1). +If you are not part of the CNCF slack workspace already, you can [get an invite here](https://communityinviter.com/apps/cloud-native/cncf). +You can also follow us on all the socials: [Twitter](http://twitter.com/OpenFeature) | [LinkedIn](https://www.linkedin.com/company/openfeature/) | [YouTube](https://www.youtube.com/channel/UCXSFt-dT2HORGXz1-ksxtxw) diff --git a/blog/2024-03-19-accouncing-web-v1.md b/blog/2024-03-19-accouncing-web-v1.md index 424ccce4f..277f13b7e 100644 --- a/blog/2024-03-19-accouncing-web-v1.md +++ b/blog/2024-03-19-accouncing-web-v1.md @@ -8,7 +8,7 @@ tags: [release, client, spec, specification, web, mobile, sdk, react] draft: false --- -We are excited to announce the availability of the [OpenFeature Web SDK v1](/docs/reference/technologies/client/web/). +We are excited to announce the availability of the [OpenFeature Web SDK v1](/docs/reference/sdks/client/web/). The Web SDK represents a culmination of years of research and industry consensus. It was built from the ground up to be performant, powerful, and flexible while providing broad support for your favorite feature management tool or in-house solution. @@ -25,7 +25,8 @@ The web framework ecosystem is massive and constantly evolving, it’s more impo ## Web vs Server At first glance, using a feature flag on the web may appear similar to server-side usage. -In many cases, this is true! However, there are subtle, yet important differences. +In many cases, this is true! +However, there are subtle, yet important differences. In OpenFeature, we have distilled these two different approaches down to static and dynamic context paradigms. The static context paradigm is commonly used on a client, and it’s the paradigm supported by the Web SDK. The rationale for introducing this paradigm can be found in our [Catering to the client-side](/blog/catering-to-the-client-side/) blog. @@ -47,12 +48,12 @@ This moves responsibility to the SDK instead of the provider author, making prov ## What's next? The Web SDK is great on its own but becomes even more powerful and user-friendly when leveraging framework-specific functionality. -The [React SDK](/docs/reference/technologies/client/web/react/) is an excellent example of this. +The [React SDK](/docs/reference/sdks/client/web/react/) is an excellent example of this. It abstracts the implementation details of supporting features like automatic component re-rendering and [built-in suspense](https://react.dev/reference/react/Suspense) support. We plan to support many more frameworks, including Angular, Vue, and Svelte. While this post is focused on the Web SDK, we haven’t forgotten about mobile. -Our friends at Spotify recently donated an initial [Kotlin](/docs/reference/technologies/client/kotlin/) and [Swift](/docs/reference/technologies/client/swift/) SDK. +Our friends at Spotify recently donated an initial [Kotlin](/docs/reference/sdks/client/kotlin/) and [Swift](/docs/reference/sdks/client/swift/) SDK. These comprise the primary technologies in the mobile space, and in concert with the Web SDK, cover the majority of client platforms. Finally, OpenFeature has been hard at work defining the [OpenFeature Remote Evaluation Protocol (OFREP)](https://github.com/open-feature/protocol). @@ -61,7 +62,9 @@ This initiative aims to standardize how feature flags can be evaluated over a ne ## Get involved OpenFeature is comprised of feature flag experts and enthusiasts. -If you'd like to [get involved](https://github.com/open-feature/community), don't be shy! Join a community call, or join the #OpenFeature [CNCF Slack](https://slack.cncf.io/) channel, and help us build a great open standard that benefits the industry. +If you'd like to [get involved](https://github.com/open-feature/community), don't be shy! +Join a community call, or join the #OpenFeature [CNCF Slack](https://slack.cncf.io/) channel, and help us build a great open standard that benefits the industry. -The [Web SDK](https://openfeature.dev/docs/reference/technologies/client/web/) is available now. Give it a shot and let us know how it goes. +The [Web SDK](https://openfeature.dev/docs/reference/sdks/client/web/) is available now. +Give it a shot and let us know how it goes. We can’t wait to see what you build! diff --git a/blog/2024-05-02-react-sdk-release.md b/blog/2024-05-02-react-sdk-release.md index d8a2f4c98..4ecd9ba39 100644 --- a/blog/2024-05-02-react-sdk-release.md +++ b/blog/2024-05-02-react-sdk-release.md @@ -8,7 +8,7 @@ tags: [react, client, sdk, web, javascript, typescript] draft: false --- -We're stoked to announce the first release of the [@openfeature/react-sdk](/docs/reference/technologies/client/web/react)! +We're stoked to announce the first release of the [@openfeature/react-sdk](/docs/reference/sdks/client/web/react)! This SDK is a distribution of our SDK for the web with extensions to support idiomatic React development and features. This blog highlights a few of these, with a few implementation details for the real React nerds. 🤓 @@ -60,6 +60,7 @@ function MyPage() { ); } ``` + Additionally, some feature flag solutions support realtime updates when flag configurations themselves are changed and the bound provider emits a [PROVIDER_CONFIGURATION_CHANGED](https://openfeature.dev/specification/types#provider-events) event. The React SDK also supports re-rendering in these cases so that a change in a flag definition immediately reflects those changes in the user interface. Both of these features can be disabled per-flag, or for the scope of the [context provider](#context-provider). @@ -115,4 +116,4 @@ Any OpenFeature provider built to support the web SDK can also be used with the We have a few enhancements in mind, particularly around mutating evaluation context and an API that provides components (in addition to hooks), but we're excited to get feedback from the community on what we've built so far! If you're a React dev (or you're just looking for an excuse to familiarize yourself with the library) take the OpenFeature React SDK for a spin and let us know how it goes! -You can play around with our test app [here](https://github.com/open-feature/react-test-app) to familiarize yourself with some of the features. \ No newline at end of file +You can play around with our test app [here](https://github.com/open-feature/react-test-app) to familiarize yourself with some of the features. diff --git a/blog/2024-09-17-announcing-angular-sdk.md b/blog/2024-09-17-announcing-angular-sdk.md index d1e91ce55..8f4b4d303 100644 --- a/blog/2024-09-17-announcing-angular-sdk.md +++ b/blog/2024-09-17-announcing-angular-sdk.md @@ -9,7 +9,7 @@ tags: [angular, ng, sdk, ts, js, javascript, web] draft: false --- -We are excited to unveil the first official release of the [@openfeature/angular-sdk](/docs/reference/technologies/client/web/angular)! 🚀 +We are excited to unveil the first official release of the [@openfeature/angular-sdk](/docs/reference/sdks/client/web/angular)! 🚀 This SDK extends OpenFeature capabilities to Angular applications, with a focus on Angular's unique patterns and practices. In this post, we’ll walk you through some of the standout features and how they integrate seamlessly with Angular development. @@ -22,7 +22,7 @@ In this post, we’ll walk you through some of the standout features and how the ### Angular Module System Integration The Angular SDK exports a module that allows you to configure your [OpenFeature provider](https://openfeature.dev/docs/reference/concepts/provider) using Angular constructs. -You can set your default provider, and optionally configure additional providers for other domains. +You can set your default provider, and optionally configure additional providers for other domains. Besides configuring your provider, you'll also need to use the `OpenFeatureModule` in order to utilize the other features of the SDK. ```ts @@ -123,4 +123,4 @@ Any OpenFeature provider built to support the web SDK can also be used with the We’re eager to expand the Angular SDK’s capabilities with future updates! If you're an Angular developer or interested in exploring how feature flags can enhance your applications, we encourage you to try out the OpenFeature Angular SDK. -Happy coding! 🎉 \ No newline at end of file +Happy coding! 🎉 diff --git a/blog/2024-12-09-kubecon-wrapped-and-tracking.md b/blog/2024-12-09-kubecon-wrapped-and-tracking.md index d42ea9d39..ac4c05f5c 100644 --- a/blog/2024-12-09-kubecon-wrapped-and-tracking.md +++ b/blog/2024-12-09-kubecon-wrapped-and-tracking.md @@ -9,7 +9,8 @@ tags: [tracking, specification, experimentation, spec, kubecon, cncf] draft: false --- -Hello from the OpenFeature community! This post is a double-feature of sorts: we'll be wrapping up our time at KubeCon NA 2024 as well as talking about our latest SDK feature: [✨ _tracking events_ ✨](/blog/kubecon-wrapped-and-tracking#robust-experimentation-support-with-tracking-events). +Hello from the OpenFeature community! +This post is a double-feature of sorts: we'll be wrapping up our time at KubeCon NA 2024 as well as talking about our latest SDK feature: [✨ _tracking events_ ✨](/blog/kubecon-wrapped-and-tracking#robust-experimentation-support-with-tracking-events). @@ -47,12 +48,13 @@ The new [Tracking API](/specification/sections/tracking) defines interfaces and In fact, if your vendor or home-grown feature flag solution doesn't support equivalent functionality, [hooks](/specification/sections/hooks) and tracking compose a flexible solution to associate flag evaluations with usage data, regardless of whatever customer data platform or telemetry backend you use. For more information, see [tracking concepts](/docs/reference/concepts/tracking). -These enhancements were brought to you by the hard work of many feature flag vendors, enterprises, and subject matter experts... Thanks to all who helped! +These enhancements were brought to you by the hard work of many feature flag vendors, enterprises, and subject matter experts... +Thanks to all who helped! ### Implementations and Future Plans Tracking event functionality is already implemented in our React, Javascript, Java, and Go SDKs, with more on the way. -For an up-to-date list of implementations, check out the [SDK Compatibility Overview](/docs/reference/technologies/sdk-compatibility). +For an up-to-date list of implementations, check out the [SDK Compatibility Overview](/docs/reference/sdks/sdk-compatibility). Download the latest release in your language of choice and try it out! diff --git a/blog/2025-03-19-devcycle-march-hackathon.md b/blog/2025-03-19-devcycle-march-hackathon.md index 1ae254666..7af42f8ff 100644 --- a/blog/2025-03-19-devcycle-march-hackathon.md +++ b/blog/2025-03-19-devcycle-march-hackathon.md @@ -21,7 +21,8 @@ Let's take a closer look at how our team hacked, what we learned, and why these ### OpenFeature Remote Evaluation Protocol with Cloudflare Workers -At DevCycle, we were an early supporters of the [OpenFeature Remote Evaluation Protocol (OFREP)](https://openfeature.dev/specification/appendix-c), and long-time users of [Cloudflare Workers](https://developers.cloudflare.com/workers/). Naturally, we were curious if we could use the OFREP API as a bridge interface to better support Feature Flags in these edge environments. +At DevCycle, we were an early supporters of the [OpenFeature Remote Evaluation Protocol (OFREP)](https://openfeature.dev/specification/appendix-c), and long-time users of [Cloudflare Workers](https://developers.cloudflare.com/workers/). +Naturally, we were curious if we could use the OFREP API as a bridge interface to better support Feature Flags in these edge environments. As one of our hackathon projects, Elliot from our team built a [DevCycle OFREP Worker](https://github.com/DevCycleHQ-Sandbox/OFREP-bucketing-worker), which we could publish for customers to run in their own environment. This worker can use a [service binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/) to bind this worker to any of their own internal workers. @@ -164,9 +165,9 @@ Our goal is to provide OpenFeature support across all DevCycle SDKs, with only N ### Dogfooding OpenFeature SDK Nest.js SDK + Providers -In the spirit of dogfooding OpenFeature and our own Providers, Kaushal from our team took up the task of updating the usage of DevCycle's Nest.js SDK in our main API service to use the [OpenFeature Nest.js SDK](https://openfeature.dev/docs/reference/technologies/server/javascript/nestjs/) with [DevCycle's Nest.js Provider](https://docs.devcycle.com/sdk/server-side-sdks/nestjs/nestjs-openfeature). +In the spirit of dogfooding OpenFeature and our own Providers, Kaushal from our team took up the task of updating the usage of DevCycle's Nest.js SDK in our main API service to use the [OpenFeature Nest.js SDK](https://openfeature.dev/docs/reference/sdks/server/javascript/nestjs/) with [DevCycle's Nest.js Provider](https://docs.devcycle.com/sdk/server-side-sdks/nestjs/nestjs-openfeature). -To accomplish this, we introduced a wrapper service that used a single instance of the OpenFeature Client, making it accessible across our Nest.js service. +To accomplish this, we introduced a wrapper service that used a single instance of the OpenFeature Client, making it accessible across our Nest.js service. This straightforward migration allowed the OpenFeature Client to replace any existing calls to DevCycle's SDK. One of the key takeaways from this project was realizing how much our API development relied on Nest.js decorators, which simplified our feature flagging of API endpoints: @@ -186,7 +187,7 @@ Dogfooding the OpenFeature SDKs and our own providers was a valuable learning ex - **Evaluation Reasons for SDKs** – Enhancing our SDKs with evaluation reasons, bringing us closer to full OpenFeature spec compliance. - **Feature Flag Observability** – Improving insights into how feature flags impact performance and decision-making. -- **Add Tracking support to more SDKs** - [OpenFeature SDK Tracking Support](https://openfeature.dev/docs/reference/technologies/sdk-compatibility#server-side-sdks) +- **Add Tracking support to more SDKs** - [OpenFeature SDK Tracking Support](https://openfeature.dev/docs/reference/sdks/sdk-compatibility#server-side-sdks) - **Multi-Provider Expansion** – Bringing multi-provider support to more languages. And many more! diff --git a/blog/2025-11-07-kubecon-na-25.md b/blog/2025-11-07-kubecon-na-25.md new file mode 100644 index 000000000..0a991b795 --- /dev/null +++ b/blog/2025-11-07-kubecon-na-25.md @@ -0,0 +1,112 @@ +--- +title: "Join OpenFeature at KubeCon + CloudNativeCon North America 2025!" +description: "Get ready for KubeCon + CloudNativeCon North America 2025 in Atlanta, Georgia! Here's everything you need to know about the OpenFeature Summit and feature flag talks." +date: 2025-11-07 +categories: ["OpenFeature", "KubeCon", "Feature Flags", "CloudNative"] +slug: "kubecon-na-2025-openfeature-summit-preview" +authors: ["toddbaert"] +image: /img/blog/2025-11-07-kubecon-na-25/kubecon-na-25.png +--- + +KubeCon + CloudNativeCon North America 2025 is just around the corner! Hosted in **Atlanta, Georgia, from November 10-13**, this year’s event is packed with exciting sessions and discussions. Again among the highlights is the **OpenFeature Summit**, a co-located event dedicated to feature flagging and progressive delivery. + + + + + +--- + +## **OpenFeature Summit Agenda** + +📅 **Date:** Monday, November 10, 2025 +📍 **Location:** Building B | Level 2 | B213-214 + +### **Doctor Flag: Into the Kubernetes Featureverse with k0rdent and OpenFeature** +**Prithvi Raj (Mirantis)** +**Time:** 1:35 PM EST + +Discover how Kubernetes and OpenFeature can work together to create powerful feature flagging solutions. Learn about the integration of k0rdent with OpenFeature to simplify feature flagging in Kubernetes environments. + +--- + +### **AI Ships Fast and Breaks Things — Feature Flags Keep It Controlled** +**Jonathan Norris (DevCycle)** +**Time:** 2:10 PM EST + +Explore how feature flags can help manage the risks of deploying AI-driven changes at scale. Jonathan will share insights on using feature flags to enable faster iterations and controlled rollouts. + +--- + +### **Feature Flag-Driven Development… in Reverse** +**Robert Erez (Octopus Deploy)** +**Time:** 2:45 PM EST + +Robert Erez will explore the concept of "reverse engineering" feature flag-driven development and provide a unique perspective on improving software delivery pipelines. + +--- + +### **From “What Broke?” To “What Changed?”: Unlocking Feature Flag Observability** +**Parth Suthar (DevCycle) & Michael Beemer (Dynatrace)** +**Time:** 3:25 PM EST + +Learn how feature flags can enhance observability, helping teams quickly identify and address issues in their applications. Parth and Michael will share practical examples of integrating feature flag observability into your workflows. + +--- + +### **Blueprint for Building Programmable CI Pipelines Using OpenFeature** +**Gaurav Saxena** +**Time:** 4:00 PM EST + +Gaurav Saxena will share a detailed blueprint for creating programmable CI pipelines using OpenFeature, showcasing how to streamline development workflows and improve efficiency. + +--- + +### **Skip the Deployment Queue: Automated Rollouts and Rollbacks Using OpenFeature** +**Ekansh Gupta (SigNoz) & Shivay Lamba (Couchbase)** +**Time:** 4:35 PM EST + +Ekansh Gupta and Shivay Lamba will discuss strategies for automating rollouts and rollbacks with OpenFeature, enabling teams to deploy more confidently and effectively. + +--- + +### **Lightning Talk: No More If-Else Soup: Scalable Feature Flag Architecture With Design Patterns** +**Gaurika Poplai (Microsoft)** +**Time:** 5:05 PM EST + +Gaurika Poplai will deliver an engaging lightning talk on how to design scalable feature flag architectures using proven design patterns. + +--- + +## **Key Feature Flag Talks at KubeCon** + +In addition to the OpenFeature Summit, don’t miss these exciting feature flag-focused sessions during KubeCon + CloudNativeCon: + +--- + +### **Feature Flags Suck! - The Problems With Feature Flagging and How To Avoid Them** +**Speaker:** Pete Hodgson (PH1) +**Time:** Thursday, November 13, 11:00 AM - 11:30 AM EST +**Location:** Building B | Level 5 | Thomas Murphy Ballroom 2-3 + +Pete Hodgson will dive into the common pitfalls of feature flagging and how to avoid them. Learn how to manage feature flags effectively and leverage CNCF's OpenFeature project to streamline your workflows. + +[Read more about this session here.](https://kccncna2025.sched.com/event/27FdI/feature-flags-suck-the-problems-with-feature-flagging-and-how-to-avoid-them-pete-hodgson-ph1?iframe=no&w=&sidebar=yes&bg=no) + +--- + +### **Feature Flag Driven Development: Seamlessly Integrate Feature Flags Into Your SDLC** +**Speakers:** Kris Coleman (TestifySec) & Michael Beemer (Dynatrace) +**Time:** Thursday, November 13, 3:15 PM - 3:45 PM EST +**Location:** Building B | Level 4 | B406b-407 + +Kris Coleman and Michael Beemer will introduce Feature Flag Driven Development (FFDD), a groundbreaking workflow that integrates feature flag management into the SDLC. Their demo will showcase how FFDD leverages CNCF's OpenFeature spec and tools like the OpenFeature CLI to enable type-safe, GitOps-driven flag promotion. + +[Read more about this session here.](https://kccncna2025.sched.com/event/27FfH/feature-flag-driven-development-seamlessly-integrate-feature-flags-into-your-sdlc-kris-coleman-testifysec-michael-beemer-dynatrace?iframe=no&w=&sidebar=yes&bg=no) + +--- + +We’re excited to see you at **KubeCon + CloudNativeCon North America 2025** and the **OpenFeature Summit**! Don’t miss this chance to connect with the OpenFeature community, learn from industry leaders, and explore the future of feature flagging. + +👉 **[Register for KubeCon + CloudNativeCon North America 2025](https://events.linuxfoundation.org/kubecon-cloudnativecon-north-america/register/)** 👈 + +Follow us on [Twitter](https://twitter.com/openfeature) or [Bluesky](https://bsky.app/profile/openfeature.dev) for live updates during the event. See you in Atlanta! diff --git a/blog/2025-11-18-kubecon-na-recap-and-new-cncf-training.md b/blog/2025-11-18-kubecon-na-recap-and-new-cncf-training.md new file mode 100644 index 000000000..5c5cfe313 --- /dev/null +++ b/blog/2025-11-18-kubecon-na-recap-and-new-cncf-training.md @@ -0,0 +1,60 @@ +--- +title: "KubeCon NA 2025 Recap and New CNCF Training" +description: "KubeCon NA 2025 Recap... and a Special Announcement!" +date: 2025-11-18 +categories: ["OpenFeature", "KubeCon", "Feature Flags", "CloudNative", "Training", "LFS140"] +slug: "kubecon-na-2025-recap" +authors: ["toddbaert"] +image: /img/blog/2025-11-18-kubecon-na-recap-and-new-cncf-training/sign.jpg +--- + +# KubeCon NA 2025 Recap and New CNCF Training + +What an incredible week! +KubeCon North America 2025 has officially finished up, and we're still reflecting on all the energy, conversations, and sessions. +If you couldn't make it, don't worry, we've got you covered with all the highlights as well as some exciting news... + + + + + +## A Successful Summit + +First off, a huge thank you to everyone who joined us at the OpenFeature Summit. +It was great to see a room full of users and contributors to the project. +We loved seeing so many of you there, asking thoughtful questions, and sharing your own experiences with feature flagging. +Thanks again to our summit sponsor, [LaunchDarkly](https://launchdarkly.com/)! + +Check out the [summit summary page](https://colocatedeventsna2025.sched.com/overview/type/OpenFeature+Summit) for recordings and slide presentations. + + + +## Feature Flag Talks + +We also hosted two incredible talks that were all about feature flags and OpenFeature. +Both sessions were well-attended, and questions and conversations kept going long after the talks ended. +It's clear that feature flagging is a hot topic, and we're thrilled to see so much interest in the space. + +🔥 [Feature Flags Suck! - The Problems With Feature Flagging and How To Avoid Them](https://kccncna2025.sched.com/event/27FdI/feature-flags-suck-the-problems-with-feature-flagging-and-how-to-avoid-them-pete-hodgson-ph1) + +📈 [Feature Flag Driven Development: Seamlessly Integrate Feature Flags Into Your SDLC](https://kccncna2025.sched.com/event/27FfH/feature-flag-driven-development-seamlessly-integrate-feature-flags-into-your-sdlc-kris-coleman-testifysec-michael-beemer-dynatrace) + + + +## New CNCF Training Course: Feature Flagging with OpenFeature + +

+ +

+ +We're happy to announce the launch of our official CNCF training course: [Feature Flagging with OpenFeature (LFS140)](https://training.linuxfoundation.org/training/feature-flagging-with-openfeature-lfs140/). +This course is perfect for developers and platform engineers who want to learn how to integrate feature flags into their workflows or enhance their apps and platforms with OpenFeature. +It covers everything from the basics of feature flagging to advanced use cases, and it's a great way to level up your skills. +Check it out! + + + +As always, we were excited to hear about new adopters, stories, and usage of the OpenFeature project at the booth. +Thanks again to everyone who made KubeCon NA 2025 such an unforgettable experience. +Whether you joined us in person or follow along online, we're so grateful for your support. +Here's to continuing the conversation and building the future of feature flagging together! \ No newline at end of file diff --git a/docs/reference/contributing.md b/docs/reference/contributing.md index be398dc4b..b459ad07c 100644 --- a/docs/reference/contributing.md +++ b/docs/reference/contributing.md @@ -1,6 +1,7 @@ --- id: contributing title: Contributing +sidebar_position: 5 --- ## Providing Feedback diff --git a/docs/reference/other-technologies/_category_.json b/docs/reference/other-technologies/_category_.json new file mode 100644 index 000000000..25a7e03ba --- /dev/null +++ b/docs/reference/other-technologies/_category_.json @@ -0,0 +1,11 @@ +{ + "label": "Other Technologies", + "position": 4, + "collapsible": true, + "collapsed": false, + "link": { + "type": "generated-index", + "title": "Other Technologies", + "description": "OpenFeature protocols, tools, and integrations for feature flag management across various technologies and platforms." + } +} \ No newline at end of file diff --git a/docs/reference/other-technologies/cli.mdx b/docs/reference/other-technologies/cli.mdx new file mode 100644 index 000000000..9914d0b5b --- /dev/null +++ b/docs/reference/other-technologies/cli.mdx @@ -0,0 +1,356 @@ +--- +title: OpenFeature CLI +sidebar_label: CLI +sidebar_position: 1 +id: cli +--- + +

+ + work-in-progress + + + Slack + +

+ +The OpenFeature CLI is a command-line tool designed to improve the developer experience when working with feature flags. +It helps developers manage feature flags consistently across different environments and programming languages by providing powerful utilities for code generation, flag validation, and more. + +The CLI bridges the gap between feature flag management systems and your application code by generating strongly typed flag accessors from a flag manifest. This approach provides: + +- **Type Safety**: Generate strongly-typed flag accessors for your preferred language +- **Developer Experience**: Reduce errors and improve IDE autocomplete support +- **Language Support**: Generate code for TypeScript, JavaScript, React, Go, C#, and more + +## Installation + +### via curl + +The OpenFeature CLI can be installed using a shell command. +This method is suitable for most Unix-like operating systems. + +```bash +curl -fsSL https://openfeature.dev/scripts/install_cli.sh | sh +``` + +### via Docker + +The OpenFeature CLI is available as a Docker image in the [GitHub Container Registry](https://github.com/open-feature/cli/pkgs/container/cli). + +You can run the CLI in a Docker container using the following command: + +```bash +docker run -it -v $(pwd):/local -w /local ghcr.io/open-feature/cli:latest +``` + +### via Go + +If you have `Go >= 1.23` installed, you can install the CLI using the following command: + +```bash +go install github.com/open-feature/cli/cmd/openfeature@latest +``` + +### via pre-built binaries + +Download the appropriate pre-built binary from the [releases page](https://github.com/open-feature/cli/releases). + +## Quick Start + +1. Create a flag manifest file in your project root: + +```bash +cat > flags.json << EOL +{ + "$schema": "https://raw.githubusercontent.com/open-feature/cli/refs/heads/main/schema/v0/flag-manifest.json", + "flags": { + "enableMagicButton": { + "flagType": "boolean", + "defaultValue": false, + "description": "Activates a special button that enhances user interaction with magical, intuitive functionalities." + } + } +} +EOL +``` + +> [!NOTE] +> This is for demonstration purposes only. +> In a real-world scenario, you would typically want to fetch this file from a remote flag management service. +> See [here](https://github.com/open-feature/cli/issues/3), more details. + +2. Generate code for your preferred language: + +```bash +openfeature generate react +``` + +See [here](https://github.com/open-feature/cli/blob/main/docs/commands/openfeature_generate.md) for all available options. + +3. View the generated code: + +```bash +cat openfeature.ts +``` + +**Congratulations!** +You have successfully generated your first strongly typed flag accessors. +You can now use the generated code in your application to access the feature flags. +This is just scratching the surface of what the OpenFeature CLI can do. +For more advanced usage, read on! + +## Commands + +The OpenFeature CLI provides the following commands: + +| Command | Description | +|---------|-------------| +| `init` | Initialize a new flag manifest | +| `manifest` | Manage flag manifest files (add, list) | +| `compare` | Compare two flag manifests | +| `generate` | Generate strongly typed flag accessors | +| `pull` | Fetch flags from remote sources | +| `push` | Push flags to remote services | +| `version` | Display CLI version | + +### `init` + +Initialize a new flag manifest in your project. + +```bash +openfeature init +``` + +This command creates a `flags.json` file in your current directory with the proper schema reference. +You can customize the manifest path using configuration options. + +See [here](https://github.com/open-feature/cli/blob/main/docs/commands/openfeature_init.md) for all available options. + +### `manifest` + +Manage flag manifest files with subcommands for adding and listing flags. + +```bash +# Add a new flag interactively +openfeature manifest add + +# Add a boolean flag +openfeature manifest add new-feature --default-value false + +# Add a string flag with description +openfeature manifest add welcome-message \ + --type string \ + --default-value "Hello!" \ + --description "Welcome message for users" + +# List all flags in the manifest +openfeature manifest list +``` + +The manifest command provides: +- **add**: Add new flags to your manifest file +- **list**: Display all flags with their configuration + +See [here](https://github.com/open-feature/cli/blob/main/docs/commands/openfeature_manifest.md) for all available options. + +### `compare` + +Compare two feature flag manifests and display the differences. + +```bash +# Compare your local manifest against another +openfeature compare --against production-flags.json + +# Compare with different output formats +openfeature compare --against other.json --output json +openfeature compare --against other.json --output yaml +openfeature compare --against other.json --output flat +``` + +Output formats: +- **tree**: Hierarchical tree view (default) +- **flat**: Simple flat list +- **json**: JSON format +- **yaml**: YAML format + +See [here](https://github.com/open-feature/cli/blob/main/docs/commands/openfeature_compare.md) for all available options. + +### `generate` + +Generate strongly typed flag accessors for your project. + +```bash +# List available languages +openfeature generate + +# Generate for a specific language +openfeature generate typescript + +# With custom output directory +openfeature generate typescript --output ./src/flags +``` + +**Supported Languages:** + +| Language | Description | +|----------|-------------| +| `typescript` | TypeScript flag accessors | +| `javascript` | JavaScript flag accessors | +| `react` | React hooks for feature flags | +| `go` | Go flag accessors | +| `csharp` | C# flag accessors | +| `java` | Java flag accessors | +| `python` | Python flag accessors | +| `nestjs` | NestJS flag accessors | +| `nodejs` | Node.js flag accessors | + +See [here](https://github.com/open-feature/cli/blob/main/docs/commands/openfeature_generate.md) for all available options. + +### `pull` + +Fetch feature flag configurations from a remote source. + +```bash +# Pull flags from a remote API +openfeature pull --flag-source-url https://api.example.com + +# With authentication +openfeature pull --flag-source-url https://api.example.com --auth-token secret-token + +# Pull from a JSON file URL +openfeature pull --flag-source-url https://example.com/flags.json +``` + +The pull command supports: +- HTTP/HTTPS endpoints implementing the OpenFeature Manifest Management API +- Direct JSON/YAML file URLs +- Authentication via bearer tokens + +See [here](https://github.com/open-feature/cli/blob/main/docs/commands/openfeature_pull.md) for all available options. + +### `push` + +Push local flag configurations to a remote flag management service. + +```bash +# Push flags to a remote API +openfeature push --flag-source-url https://api.example.com --auth-token secret-token + +# Dry run to preview changes +openfeature push --flag-source-url https://api.example.com --dry-run +``` + +The push command intelligently: +- Fetches existing flags from the remote +- Compares local flags with remote flags +- Creates new flags that don't exist remotely +- Updates existing flags that have changed + +See [here](https://github.com/open-feature/cli/blob/main/docs/commands/openfeature_push.md) for all available options. + +### `version` + +Print the version number of the OpenFeature CLI. + +```bash +openfeature version +``` + +See [here](https://github.com/open-feature/cli/blob/main/docs/commands/openfeature_version.md) for all available options. + +## Flag Manifest + +The flag manifest is a JSON file that defines your feature flags and their properties. +It serves as the source of truth for your feature flags and is used by the CLI to generate strongly typed accessors. +The manifest file should be named `flags.json` and placed in the root of your project. + +### Flag Manifest Structure + +The flag manifest file should follow the [JSON schema](https://raw.githubusercontent.com/open-feature/cli/refs/heads/main/schema/v0/flag-manifest.json) with the following properties: + +- `$schema` - The URL of the JSON schema for validation +- `flags` - An object containing the feature flags + - `flagKey` - A unique key for the flag + - `description` - A description of what the flag does + - `type` - The type of the flag (`boolean`, `string`, `number`, `object`) + - `defaultValue` - The default value of the flag + +### Example Flag Manifest + +```json +{ + "$schema": "https://raw.githubusercontent.com/open-feature/cli/refs/heads/main/schema/v0/flag-manifest.json", + "flags": { + "uniqueFlagKey": { + "description": "Description of what this flag does", + "type": "boolean|string|number|object", + "defaultValue": "default-value", + } + } +} +``` + +## Remote Flag Management + +The OpenFeature CLI supports synchronizing flags with remote flag management services through a standardized OpenAPI-based approach. This enables teams to: + +- **Pull flags** from centralized flag management systems +- **Push flags** back to maintain consistency across environments +- **Integrate** with any service that implements the Manifest Management API + +### OpenAPI Client Pattern + +The CLI uses an OpenAPI-driven architecture for remote operations: + +1. **Standardized API**: All remote operations conform to the [Manifest Management API](https://github.com/open-feature/cli/blob/main/api/v0/sync.yaml) OpenAPI specification +2. **Type-Safe Clients**: Generated clients provide compile-time safety and better IDE support +3. **Provider Agnostic**: Any service implementing the API specification can integrate with the CLI + +For detailed information about implementing or extending the OpenAPI client pattern, see the [OpenAPI Client Pattern documentation](https://github.com/open-feature/cli/blob/main/docs/openapi-client-pattern.md). + +### Implementing the Manifest Management API + +If you're building a flag management service that needs to integrate with the OpenFeature CLI, implement the endpoints defined in the [sync.yaml](https://github.com/open-feature/cli/blob/main/api/v0/sync.yaml) specification: + +- `GET /openfeature/v0/manifest` - Retrieve the project manifest +- `POST /openfeature/v0/manifest/flags` - Create new flags +- `PUT /openfeature/v0/manifest/flags/{key}` - Update existing flags +- `DELETE /openfeature/v0/manifest/flags/{key}` - Archive/delete flags + +## Configuration + +The OpenFeature CLI uses an optional configuration file to override default settings and customize behavior. +This file can be in JSON or YAML format and should be named either `.openfeature.json` or `.openfeature.yaml`. + +### Configuration File Structure + +```yaml +# Example .openfeature.yaml +manifest: "flags/manifest.json" # Overrides the default manifest path +generate: + output: "src/flags" # Overrides the default output directory + # Any language-specific options can be specified here + # For example, for React: + react: + output: "src/flags/react" # Overrides the default React output directory + # For Go: + go: + package: "github.com/myorg/myrepo/flags" # Overrides the default Go package name + output: "src/flags/go" # Overrides the default Go output directory +``` + +### Configuration Priority + +The CLI uses a layered approach to configuration, allowing you to override settings at different levels. +The configuration is applied in the following order: + +```mermaid +flowchart LR + default("Default Config") + config("Config File") + args("Command Line Args") + default --> config + config --> args +``` + diff --git a/docs/reference/other-technologies/mcp.mdx b/docs/reference/other-technologies/mcp.mdx new file mode 100644 index 000000000..7729b078f --- /dev/null +++ b/docs/reference/other-technologies/mcp.mdx @@ -0,0 +1,275 @@ +--- +title: OpenFeature MCP Server +sidebar_label: MCP +sidebar_position: 3 +id: mcp +--- + +The **OpenFeature Model Context Protocol (MCP) Server** enables AI coding assistants to interact with OpenFeature through a standardized protocol. +It provides SDK installation guidance and feature flag evaluation capabilities directly within your AI-powered development environment. + +The OpenFeature MCP Server is a local tool that connects AI coding assistants (like **Cursor**, **Claude Code**, **VS Code**, and **Windsurf**) to OpenFeature functionality. +It acts as a bridge between your AI assistant and OpenFeature capabilities, enabling intelligent code generation and migration, SDK installation guidance, and feature flag evaluation. + +This server is published to the [MCP Registry](https://registry.modelcontextprotocol.io) under `dev.openfeature/mcp`. + +> **⚠️ AI Agent Behavior**: AI agents are non-deterministic and may not complete tasks correctly. Always manually review their changes before committing. If you encounter issues, please [open an issue](https://github.com/open-feature/mcp/issues) with details about your AI agent (e.g., Claude Code + Sonnet 4.5, Cursor + gpt-5-codex) with the commands you used and the behavior you saw. + +## Quick Start + +### NPX Install + +The easiest way to use the OpenFeature MCP Server is through NPX, which requires no installation: + +```json +{ + "mcpServers": { + "OpenFeature": { + "command": "npx", + "args": ["-y", "@openfeature/mcp"] + } + } +} +``` + +### NPM Global Install + +You can install the MCP server globally: + +```bash +npm install -g @openfeature/mcp +``` + +Then configure your AI assistant to use the global installation: + +```json +{ + "mcpServers": { + "OpenFeature": { + "command": "openfeature-mcp" + } + } +} +``` + +## AI Assistant Configuration + +### Cursor + +📦 Install in Cursor + +To open Cursor and automatically add the OpenFeature MCP, click the install button above. + +Alternatively, navigate to `Cursor Settings` -> `Tools & MCP` -> `New MCP Server` and add to `~/.cursor/mcp_settings.json`: + +```json +{ + "mcpServers": { + "OpenFeature": { + "command": "npx", + "args": ["-y", "@openfeature/mcp"] + } + } +} +``` + +### VS Code + +📦 Install in VS Code + +To open VS Code and automatically add the OpenFeature MCP, click the install button above. +For more details, see the [VS Code MCP documentation](https://code.visualstudio.com/docs/copilot/customization/mcp-servers). + +Alternatively, add to `.vscode/mcp.json` in your project: + +```json +{ + "mcpServers": { + "OpenFeature": { + "command": "npx", + "args": ["-y", "@openfeature/mcp"], + "env": { // Optional environment variables + "OPENFEATURE_OFREP_BASE_URL": "", + "OPENFEATURE_OFREP_API_KEY": "" + } + } + } +} +``` + +### Claude Code + +Add the server via the Claude Code CLI: + +```bash +claude mcp add --transport stdio openfeature npx -y @openfeature/mcp +``` + +Then manage the connection with `/mcp` in the CLI. + +### Windsurf + +In the `Manage MCP servers` raw config, add: + +```json +{ + "mcpServers": { + "OpenFeature": { + "command": "npx", + "args": ["-y", "@openfeature/mcp"] + } + } +} +``` + +### Codex CLI + +Edit `~/.codex/config.toml`: + +```toml +[mcp_servers.openfeature] +command = "npx" +args = ["-y", "@openfeature/mcp"] +``` + +Restart Codex CLI after saving. + +### Gemini CLI + +Edit `~/.gemini/settings.json`: + +```json +{ + "mcpServers": { + "OpenFeature": { + "command": "npx", + "args": ["-y", "@openfeature/mcp"] + } + } +} +``` + +Restart Gemini CLI after saving. + +### Claude Desktop + +Edit your Claude Desktop config at: + +- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json` +- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` + +Add the following configuration: + +```json +{ + "mcpServers": { + "openfeature": { + "command": "npx", + "args": ["-y", "@openfeature/mcp"] + } + } +} +``` + +Restart Claude Desktop after saving. + +## Available Tools + +The OpenFeature MCP Server provides two main tools accessible to AI assistants: + +### SDK Installation Guide: `install_openfeature_sdk` + +Fetches installation instructions for OpenFeature SDKs in various languages and frameworks. Optionally includes provider-specific setup documentation. + +#### SDK Tool Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `technology` | string | Yes | Target language/framework (see supported list below) | +| `providers` | string[] | No | Provider identifiers to include installation instructions | + +#### Supported Technologies + +The technologies list is built from the available `prompts/*.md`, updated automatically using `scripts/build-prompts.js` + +| Technology | SDK | +|------------|-----| +| `android` | Android Kotlin SDK | +| `dotnet` | .NET SDK | +| `go` | Go SDK | +| `ios` | iOS Swift SDK | +| `java` | Java SDK | +| `javascript` | JavaScript Web SDK | +| `nestjs` | NestJS SDK | +| `nodejs` | Node.js SDK | +| `php` | PHP SDK | +| `python` | Python SDK | +| `react` | React SDK | +| `ruby` | Ruby SDK | + +#### Supported Providers + +The provider list is automatically sourced from the OpenFeature ecosystem (`open-feature/openfeature.dev` repo). + +See `scripts/build-providers.js` for details on how the provider list is maintained. + +### OFREP Flag Evaluation: `ofrep_flag_eval` + +Evaluate feature flags using the OpenFeature Remote Evaluation Protocol (OFREP). +Supports both single flag and bulk evaluation. + +#### OFREP Tool Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `base_url` | string | No | Base URL of your OFREP-compatible flag service | +| `flag_key` | string | No | Flag key for single evaluation (omit for bulk) | +| `context` | object | No | Evaluation context (e.g., `{ targetingKey: "user-123" }`) | +| `etag` | string | No | ETag for bulk evaluation caching | +| `auth` | object | No | Authentication configuration | +| `auth.bearer_token` | string | No | Bearer token for authorization | +| `auth.api_key` | string | No | API key for authorization | + +#### OFREP Configuration + +To use OFREP flag evaluation features, configure authentication and endpoint details. The server checks configuration in this priority order: + +1. **Environment Variables** + - `OPENFEATURE_OFREP_BASE_URL` or `OFREP_BASE_URL` + - `OPENFEATURE_OFREP_BEARER_TOKEN` or `OFREP_BEARER_TOKEN` + - `OPENFEATURE_OFREP_API_KEY` or `OFREP_API_KEY` + +2. **Configuration File**: `~/.openfeature-mcp.json` + +Example `~/.openfeature-mcp.json`: + +```json +{ + "OFREP": { + "baseUrl": "https://flags.example.com", + "bearerToken": "", + "apiKey": "" + } +} +``` + +You can override the config file path using the `OPENFEATURE_MCP_CONFIG_PATH` environment variable. + +> **Note**: All logs are written to stderr. The MCP protocol messages use stdout. + +## MCP Usage Examples + +### SDK Installation Example + +> "install the OpenFeature SDK for Node.js with the flagd provider" + +The AI will use the MCP to fetch relevant installation instructions and attempt to install the OpenFeature SDK with the correct provider. + +### Flag Evaluation Example + +When interacting with your AI assistant: + +> "Can you check the value of the 'new-checkout-flow' feature flag for 'user-123'?" + +The AI will use the MCP to evaluate the flag using OFREP and provide you with the result, along with additional metadata like variant and reason. + diff --git a/docs/reference/other-technologies/ofrep/_category_.json b/docs/reference/other-technologies/ofrep/_category_.json new file mode 100644 index 000000000..d37712118 --- /dev/null +++ b/docs/reference/other-technologies/ofrep/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "OFREP", + "position": 2, + "collapsible": true, + "collapsed": false, + "link": { + "type": "doc", + "id": "reference/other-technologies/ofrep/ofrep" + } +} \ No newline at end of file diff --git a/docs/reference/other-technologies/ofrep/index.mdx b/docs/reference/other-technologies/ofrep/index.mdx new file mode 100644 index 000000000..68281c575 --- /dev/null +++ b/docs/reference/other-technologies/ofrep/index.mdx @@ -0,0 +1,77 @@ +--- +title: OpenFeature Remote Evaluation Protocol (OFREP) +sidebar_label: OFREP +sidebar_position: 2 +id: ofrep +--- + +The **OpenFeature Remote Evaluation Protocol (OFREP)** is an [API specification](/docs/reference/other-technologies/ofrep/openapi) for feature flagging that enables vendor-agnostic communication between applications and flag management systems. It defines a standard API layer between the provider and the flag management system, allowing any open source or commercial system to implement the protocol and be compatible with community-maintained providers. + +### Key Benefits + +- **Vendor Agnostic**: Connect to any OFREP-compliant flag management system without vendor-specific implementations +- **Standardized**: Built on a common [OpenAPI specification](/docs/reference/other-technologies/ofrep/openapi) for consistent integration +- **Flexible**: Works on both client-side and server-side applications +- **Community Maintained**: Generic OFREP providers maintained by the OpenFeature project + +## How It Works + +OFREP is **a protocol, not a provider**. It defines how to communicate with feature flag management systems and works on top of OpenFeature SDKs by providing standardized providers. + +```mermaid +graph LR + A[Your Application] --> B[OpenFeature SDK] + B --> C[OFREP Provider] + C --> D[OFREP API] + D --> E[Flag Management System] +``` + +1. Your application uses the OpenFeature SDK +2. The OpenFeature SDK uses an OFREP provider +3. The OFREP provider communicates with your flag management system via the standardized OFREP API +4. Your flag management system implements the [OFREP specification](/docs/reference/other-technologies/ofrep/openapi) + +### Server vs Client + +OFREP supports both paradigms defined by OpenFeature: + +#### Server-Side (Dynamic Context) + +- Evaluation happens by calling the OFREP API with context +- API request with evaluation context is made on every evaluation +- Context per evaluation + +#### Client-Side (Static Context) + +- All flags are evaluated in one OFREP API call using a common static context +- Then local flag evaluation happens against the cached static context +- Context represents a single user or session + +## Using OFREP + +### Available Providers + +The OpenFeature community maintains OFREP providers for multiple languages. View the complete list of [OFREP providers in the ecosystem](https://openfeature.dev/ecosystem/?instant_search%5BrefinementList%5D%5Bvendor%5D%5B0%5D=OFREP). + +### Available Flag Management Systems + +Several flag management systems support OFREP. View the complete list of [OFREP-compliant systems in the ecosystem](https://openfeature.dev/ecosystem/?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=OFREP%20API). + +## Implementing OFREP + +### For Provider Developers + +To create an OFREP provider for a new language: + +1. Review the [server provider guideline](https://github.com/open-feature/protocol/blob/main/guideline/dynamic-context-provider.md) or [client provider guideline](https://github.com/open-feature/protocol/blob/main/guideline/static-context-provider.md) +2. Implement the provider for your SDK according to the guidelines +3. Register your provider in the [OpenFeature ecosystem](https://github.com/open-feature/openfeature.dev/issues) + +### For Flag Management System Developers + +To make your flag management system OFREP-compliant: + +1. Implement the [OFREP OpenAPI specification](/docs/reference/other-technologies/ofrep/openapi) +2. Test your implementation with existing OFREP providers +3. Register your system in the [OpenFeature ecosystem](https://github.com/open-feature/openfeature.dev/issues) + diff --git a/docs/reference/other-technologies/ofrep/openapi.mdx b/docs/reference/other-technologies/ofrep/openapi.mdx new file mode 100644 index 000000000..10cc6b452 --- /dev/null +++ b/docs/reference/other-technologies/ofrep/openapi.mdx @@ -0,0 +1,12 @@ +--- +title: "OpenAPI Spec" +sidebar_position: 2 +hide_title: true +--- + +import Redoc from '@theme/Redoc'; + +
+ +
+ diff --git a/docs/reference/technologies/server/_category_.json b/docs/reference/sdks/_category_.json similarity index 56% rename from docs/reference/technologies/server/_category_.json rename to docs/reference/sdks/_category_.json index d94fdaeef..98af3cb03 100644 --- a/docs/reference/technologies/server/_category_.json +++ b/docs/reference/sdks/_category_.json @@ -1,4 +1,6 @@ { + "label": "SDKs", + "position": 3, "collapsible": true, "collapsed": false } \ No newline at end of file diff --git a/docs/reference/technologies/_category_.json b/docs/reference/sdks/client/_category_.json similarity index 100% rename from docs/reference/technologies/_category_.json rename to docs/reference/sdks/client/_category_.json diff --git a/docs/reference/technologies/client/index.mdx b/docs/reference/sdks/client/index.mdx similarity index 100% rename from docs/reference/technologies/client/index.mdx rename to docs/reference/sdks/client/index.mdx diff --git a/docs/reference/technologies/client/kotlin.mdx b/docs/reference/sdks/client/kotlin.mdx similarity index 80% rename from docs/reference/technologies/client/kotlin.mdx rename to docs/reference/sdks/client/kotlin.mdx index b57e6a0c3..779ef90d6 100644 --- a/docs/reference/technologies/client/kotlin.mdx +++ b/docs/reference/sdks/client/kotlin.mdx @@ -10,8 +10,10 @@ This content has been automatically generated from kotlin-sdk. Edits should be made here: https://github.com/open-feature/kotlin-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:20 GMT+0000 (Coordinated Universal Time) --> +import MCPInstall from '@site/src/partials/mcp-install'; +

@@ -31,12 +33,15 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) ## Quick start + + + ### Requirements The following [Kotlin Multiplatform Targets](https://www.jetbrains.com/help/kotlin-multiplatform-dev/multiplatform-dsl-reference.html#targets) are supported: | Supported | Platform | Supported versions | -|-----------|----------------------|--------------------------------------------------------------------------------| +| --------- | -------------------- | ------------------------------------------------------------------------------ | | ✅ | Android | SDK 21+ | | ✅ | JVM | JDK 11+ | | ✅ | Native | Linux x64 | @@ -101,17 +106,18 @@ coroutineScope.launch(Dispatchers.Default) { ## Features -| Status | Features | Description | -|--------|---------------------------------|------------------------------------------------------------------------------------------------------------------------------------| -| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. | -| ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](/docs/reference/concepts/evaluation-context). | -| ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. | -| ✅ | [Tracking](#tracking) | Associate user actions with feature flag evaluations. | -| ❌ | [Logging](#logging) | Integrate with popular logging packages. | -| ❌ | [Named clients](#named-clients) | Utilize multiple providers in a single application. | -| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. | -| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | -| ⚠️ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | +| Status | Features | Description | +| ------ | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. | +| ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](/docs/reference/concepts/evaluation-context). | +| ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. | +| ✅ | [Tracking](#tracking) | Associate user actions with feature flag evaluations. | +| ❌ | [Logging](#logging) | Integrate with popular logging packages. | +| ❌ | [Domains](#domains) | Logically bind clients with providers. | +| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. | +| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | +| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | +| ✅ | [Multi-Provider](#multi-provider) | Combine multiple providers with configurable evaluation strategies. | Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌ @@ -206,9 +212,10 @@ Logging customization is not yet available in the Kotlin SDK. It is possible to write and inject logging `Hook`s to log events at different stages of the flag evaluation life-cycle. -### Named clients +### Domains -Support for named clients is not yet available in the Kotlin SDK. +Domains allow you to logically bind clients with providers. +Support for domains is not yet available in the Kotlin SDK. ### Eventing @@ -234,6 +241,16 @@ viewModelScope.launch { } ``` +### Multi-Provider + +The Multi-Provider allows you to use multiple underlying providers as sources of flag data for the OpenFeature Kotlin SDK. +When a flag is being evaluated, the Multi-Provider will use each underlying provider in order to determine the final result. +Different evaluation strategies can be defined to control which providers get evaluated and which result is used. + +The Multi-Provider is a useful tool for performing migrations between flag providers, or combining multiple providers into a single feature flagging interface. + +See the [Multi-Provider documentation](https://github.com/open-feature/kotlin-sdk/blob/main/docs/multiprovider/README.md) for more details. + ### Shutdown The OpenFeature API provides a close function to perform a cleanup of the registered provider. diff --git a/docs/reference/technologies/client/swift.mdx b/docs/reference/sdks/client/swift.mdx similarity index 80% rename from docs/reference/technologies/client/swift.mdx rename to docs/reference/sdks/client/swift.mdx index b209a9f36..41794ea21 100644 --- a/docs/reference/technologies/client/swift.mdx +++ b/docs/reference/sdks/client/swift.mdx @@ -10,8 +10,10 @@ This content has been automatically generated from swift-sdk. Edits should be made here: https://github.com/open-feature/swift-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:20 GMT+0000 (Coordinated Universal Time) --> +import MCPInstall from '@site/src/partials/mcp-install'; +

@@ -20,8 +22,8 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) - - Release + + Release @@ -31,6 +33,9 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) ## Quick start + + + ### Requirements This SDK supports the following Apple platforms: @@ -62,7 +67,7 @@ First, ensure you have your GitHub account added as an option (+ > Add Source Co If you manage dependencies through SPM, in the dependencies section of Package.swift add: ```swift -.package(url: "git@github.com:open-feature/swift-sdk.git", from: "0.4.0") +.package(url: "git@github.com:open-feature/swift-sdk.git", from: "0.5.0") ``` and in the target dependencies section add: @@ -102,17 +107,18 @@ Task { ## Features -| Status | Features | Description | -| ------ | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. | -| ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](/docs/reference/concepts/evaluation-context). | -| ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. | -| ❌ | [Tracking](#tracking) | Associate user actions with feature flag evaluations. | -| ❌ | [Logging](#logging) | Integrate with popular logging packages. | -| ✅ | [MultiProvider](#multiprovider) | Utilize multiple providers in a single application. | -| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. | -| ❌ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | -| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | +| Status | Features | Description | +| ------ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. | +| ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](/docs/reference/concepts/evaluation-context). | +| ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. | +| ✅ | [Tracking](#tracking) | Associate user actions with feature flag evaluations. | +| ❌ | [Logging](#logging) | Integrate with popular logging packages. | +| ❌ | [Domains](#domains) | Logically bind clients with providers. | +| ✅ | [MultiProvider](#multiprovider) | Combine multiple providers with configurable evaluation strategies. | +| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. | +| ❌ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | +| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌ @@ -157,7 +163,7 @@ Once you've added a hook as a dependency, it can be registered at the global, cl OpenFeatureAPI.shared.addHooks(hooks: ExampleHook()) // add a hook on this client, to run on all evaluations made by this client -val client = OpenFeatureAPI.shared.getClient() +let client = OpenFeatureAPI.shared.getClient() client.addHooks(ExampleHook()) // add a hook for this evaluation only @@ -168,15 +174,31 @@ _ = client.getValue( ``` ### Tracking -Tracking is not yet available in the iOS SDK. +The tracking API allows you to use OpenFeature abstractions and objects to associate user actions with feature flag evaluations. +This is essential for robust experimentation powered by feature flags. +For example, a flag enhancing the appearance of a UI component might drive user engagement to a new feature; to test this hypothesis, telemetry collected by a [hook](#hooks) or [provider](#providers) can be associated with telemetry reported in the client's `track` function. + +```swift +let client = OpenFeatureAPI.shared.getClient() + +// Track an event +client.track(key: "test") + +// Track an event with a numeric value +client.track(key: "test-value", details: ImmutableTrackingEventDetails(value: 5)) +``` + +Note that some providers may not support tracking; check the documentation for your provider for more information. ### Logging Logging customization is not yet available in the iOS SDK. -### Named clients +### Domains + +Domains allow you to logically bind clients with providers, enabling the use of multiple providers within a single application. Each domain can have its own provider, and clients can be associated with a specific domain. -Support for named clients is not yet available in the iOS SDK. +Support for domains is not yet available in the iOS SDK. ### MultiProvider diff --git a/docs/reference/technologies/client/web/_category_.json b/docs/reference/sdks/client/web/_category_.json similarity index 100% rename from docs/reference/technologies/client/web/_category_.json rename to docs/reference/sdks/client/web/_category_.json diff --git a/docs/reference/technologies/client/web/angular.mdx b/docs/reference/sdks/client/web/angular.mdx similarity index 74% rename from docs/reference/technologies/client/web/angular.mdx rename to docs/reference/sdks/client/web/angular.mdx index 0c17144a6..0efc3e893 100644 --- a/docs/reference/technologies/client/web/angular.mdx +++ b/docs/reference/sdks/client/web/angular.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from js-sdk. Edits should be made here: https://github.com/open-feature/js-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:20 GMT+0000 (Coordinated Universal Time) -->

@@ -18,8 +18,8 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) Specification - - Release + + Release
@@ -34,28 +34,36 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) ## Overview The OpenFeature Angular SDK adds Angular-specific functionality to -the [OpenFeature Web SDK](/docs/reference/technologies/client/web). +the [OpenFeature Web SDK](/docs/reference/sdks/client/web). -In addition to the features provided by the [web sdk](/docs/reference/technologies/client/web), capabilities include: +In addition to the features provided by the [web sdk](/docs/reference/sdks/client/web), capabilities include: - [Overview](#overview) - [Quick start](#quick-start) - - [Requirements](#requirements) - - [Install](#install) - - [npm](#npm) - - [yarn](#yarn) - - [Required peer dependencies](#required-peer-dependencies) - - [Usage](#usage) - - [Module](#module) - - [Minimal Example](#minimal-example) - - [How to use](#how-to-use) - - [Boolean Feature Flag](#boolean-feature-flag) - - [Number Feature Flag](#number-feature-flag) - - [String Feature Flag](#string-feature-flag) - - [Object Feature Flag](#object-feature-flag) - - [Opting-out of automatic re-rendering](#opting-out-of-automatic-re-rendering) - - [Consuming the evaluation details](#consuming-the-evaluation-details) - - [Setting Evaluation Context](#setting-evaluation-context) + - [Requirements](#requirements) + - [Install](#install) + - [npm](#npm) + - [yarn](#yarn) + - [Required peer dependencies](#required-peer-dependencies) + - [Usage](#usage) + - [Module](#module) + - [Minimal Example](#minimal-example) + - [How to use](#how-to-use) + - [Structural Directives](#structural-directives) + - [Boolean Feature Flag](#boolean-feature-flag) + - [Number Feature Flag](#number-feature-flag) + - [String Feature Flag](#string-feature-flag) + - [Object Feature Flag](#object-feature-flag) + - [Opting-out of automatic re-rendering](#opting-out-of-automatic-re-rendering) + - [Consuming the evaluation details](#consuming-the-evaluation-details) + - [FeatureFlagService](#featureflagservice) + - [Using with Observables](#using-with-observables) + - [Using with Angular Signals](#using-with-angular-signals) + - [Service Options](#service-options) + - [Setting evaluation context](#setting-evaluation-context) + - [Using a static object](#using-a-static-object) + - [Using a factory function](#using-a-factory-function) + - [Observability considerations](#observability-considerations) - [FAQ and troubleshooting](#faq-and-troubleshooting) - [Resources](#resources) @@ -86,9 +94,9 @@ yarn add @openfeature/angular-sdk @openfeature/web-sdk @openfeature/core The following list contains the peer dependencies of `@openfeature/angular-sdk`. See the [package.json](https://github.com/open-feature/js-sdk/blob/main/packages/angular/projects/angular-sdk/package.json) for the required versions. -* `@openfeature/web-sdk` -* `@angular/common` -* `@angular/core` +- `@openfeature/web-sdk` +- `@angular/common` +- `@angular/core` ### Usage @@ -115,11 +123,10 @@ import { OpenFeatureModule } from '@openfeature/angular-sdk'; domain1: new YourOpenFeatureProvider(), domain2: new YourOtherOpenFeatureProvider(), }, - }) + }), ], }) -export class AppModule { -} +export class AppModule {} ``` ##### Minimal Example @@ -130,9 +137,7 @@ If `initializing` and `reconciling` are not given, the feature flag value that i determine what will be rendered. ```html -

- This is shown when the feature flag is enabled. -
+
This is shown when the feature flag is enabled.
``` This example shows content when the feature flag `isFeatureEnabled` is true with a default value of true. @@ -174,72 +179,58 @@ This parameter is _optional_, if omitted, the `then` and `else` templates will b ```html
+ *booleanFeatureFlag="'isFeatureEnabled'; default: true; domain: 'userDomain'; else: booleanFeatureElse; initializing: booleanFeatureInitializing; reconciling: booleanFeatureReconciling" +> This is shown when the feature flag is enabled.
- - This is shown when the feature flag is disabled. - - - This is shown when the feature flag is initializing. - - - This is shown when the feature flag is reconciling. - + This is shown when the feature flag is disabled. + This is shown when the feature flag is initializing. + This is shown when the feature flag is reconciling. ``` ###### Number Feature Flag ```html
+ *numberFeatureFlag="'discountRate'; value: 10; default: 5; domain: 'userDomain'; else: numberFeatureElse; initializing: numberFeatureInitializing; reconciling: numberFeatureReconciling" +> This is shown when the feature flag matches the specified discount rate.
This is shown when the feature flag does not match the specified discount rate. - - This is shown when the feature flag is initializing. - - - This is shown when the feature flag is reconciling. - + This is shown when the feature flag is initializing. + This is shown when the feature flag is reconciling. ``` ###### String Feature Flag ```html
+ *stringFeatureFlag="'themeColor'; value: 'dark'; default: 'light'; domain: 'userDomain'; else: stringFeatureElse; initializing: stringFeatureInitializing; reconciling: stringFeatureReconciling" +> This is shown when the feature flag matches the specified theme color.
This is shown when the feature flag does not match the specified theme color. - - This is shown when the feature flag is initializing. - - - This is shown when the feature flag is reconciling. - + This is shown when the feature flag is initializing. + This is shown when the feature flag is reconciling. ``` ###### Object Feature Flag ```html
+ *objectFeatureFlag="'userConfig'; value: { theme: 'dark' }; default: { theme: 'light' }; domain: 'userDomain'; else: objectFeatureElse; initializing: objectFeatureInitializing; reconciling: objectFeatureReconciling" +> This is shown when the feature flag matches the specified user configuration.
This is shown when the feature flag does not match the specified user configuration. - - This is shown when the feature flag is initializing. - - - This is shown when the feature flag is reconciling. - + This is shown when the feature flag is initializing. + This is shown when the feature flag is reconciling. ``` ###### Opting-out of automatic re-rendering @@ -249,7 +240,9 @@ By default, the directive re-renders when the flag value changes or the context In cases, this is not desired, re-rendering can be disabled for both events: ```html -
+
This is shown when the feature flag is enabled.
``` @@ -266,13 +259,12 @@ The following example shows `value` being implicitly bound and `details` being b ```html
- It was a match! - The theme color is {{ value }} because of {{ details.reason }} + *stringFeatureFlag="'themeColor'; value: 'dark'; default: 'light'; else: stringFeatureElse; let value; let details = evaluationDetails" +> + It was a match! The theme color is {{ value }} because of {{ details.reason }}
- - It was no match! - The theme color is {{ value }} because of {{ details.reason }} + + It was no match! The theme color is {{ value }} because of {{ details.reason }} ``` @@ -280,9 +272,7 @@ When the expected flag value is omitted, the template will always be rendered. This can be used to just render the flag value or details without conditional rendering. ```html -
- The theme color is {{ value }}. -
+
The theme color is {{ value }}.
``` ##### FeatureFlagService @@ -307,7 +297,7 @@ import { FeatureFlagService } from '@openfeature/angular-sdk';
Theme: {{ (currentTheme$ | async)?.value }}
Max items: {{ (maxItems$ | async)?.value }}
- ` + `, }) export class MyComponent { private flagService = inject(FeatureFlagService); @@ -339,11 +329,9 @@ import { FeatureFlagService } from '@openfeature/angular-sdk'; selector: 'my-component', standalone: true, template: ` -
- Feature is enabled! Reason: {{ isFeatureEnabled()?.reason }} -
+
Feature is enabled! Reason: {{ isFeatureEnabled()?.reason }}
Theme: {{ currentTheme()?.value }}
- ` + `, }) export class MyComponent { private flagService = inject(FeatureFlagService); @@ -360,8 +348,8 @@ The service methods accept the [same options as the directives](#opting-out-of-a ```typescript const flag$ = this.flagService.getBooleanDetails('my-flag', false, 'my-domain', { - updateOnConfigurationChanged: false, // default: true - updateOnContextChanged: false, // default: true + updateOnConfigurationChanged: false, // default: true + updateOnContextChanged: false, // default: true }); ``` @@ -386,7 +374,7 @@ const initialContext = { user: { id: 'user123', role: 'admin', - } + }, }; @NgModule({ @@ -394,8 +382,8 @@ const initialContext = { CommonModule, OpenFeatureModule.forRoot({ provider: yourFeatureProvider, - context: initialContext - }) + context: initialContext, + }), ], }) export class AppModule {} @@ -415,13 +403,19 @@ const contextFactory = (): EvaluationContext => loadContextFromLocalStorage(); CommonModule, OpenFeatureModule.forRoot({ provider: yourFeatureProvider, - context: contextFactory - }) + context: contextFactory, + }), ], }) export class AppModule {} ``` +##### Observability considerations + +Angular's lifecycle can result in flags being evaluated multiple times as a user interacts with a page. +If you are using an OpenFeature hook for telemetry, this can result in inflated evaluation metrics. +The [OpenFeature debounce hook](https://github.com/open-feature/js-sdk-contrib/tree/main/libs/hooks/debounce) can help to reduce the amount of redundant evaluations reported to your observability platform by limiting the frequency at which evaluation metrics are reported. + ## FAQ and troubleshooting > I can import things form the `@openfeature/angular-sdk`, `@openfeature/web-sdk`, and `@openfeature/core`; which should I use? diff --git a/docs/reference/technologies/client/web/index.mdx b/docs/reference/sdks/client/web/index.mdx similarity index 70% rename from docs/reference/technologies/client/web/index.mdx rename to docs/reference/sdks/client/web/index.mdx index dc868d7f4..12c2bd15e 100644 --- a/docs/reference/technologies/client/web/index.mdx +++ b/docs/reference/sdks/client/web/index.mdx @@ -10,16 +10,18 @@ This content has been automatically generated from js-sdk. Edits should be made here: https://github.com/open-feature/js-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:20 GMT+0000 (Coordinated Universal Time) --> +import MCPInstall from '@site/src/partials/mcp-install'; +

Specification - - Release + + Release
@@ -39,6 +41,9 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) ## Quick start + + + ### Requirements - ES2015-compatible web browser (Chrome, Edge, Firefox, etc) @@ -52,7 +57,7 @@ npm install --save @openfeature/web-sdk ``` > [!TIP] -> This SDK is designed to run in the browser. If you're interested in server support, check out the [Node.js SDK](/docs/reference/technologies/server/javascript/). +> This SDK is designed to run in the browser. If you're interested in server support, check out the [Node.js SDK](/docs/reference/sdks/server/javascript/). #### yarn @@ -85,7 +90,7 @@ const client = OpenFeature.getClient(); const v2Enabled = client.getBooleanValue('v2_enabled', false); if (v2Enabled) { - console.log("v2 is enabled"); + console.log('v2 is enabled'); } ``` @@ -97,15 +102,16 @@ See [here](https://open-feature.github.io/js-sdk/modules/_openfeature_web_sdk.ht | Status | Features | Description | | ------ | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. | -| ✅ | [Targeting](#targeting-and-context) | Contextually-aware flag evaluation using [evaluation context](/docs/reference/concepts/evaluation-context). | -| ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. | -| ✅ | [Logging](#logging) | Integrate with popular logging packages. | -| ✅ | [Domains](#domains) | Logically bind clients with providers. | -| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. | -| ✅ | [Tracking](#tracking) | Associate user actions with feature flag evaluations, particularly for A/B testing. | -| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | -| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | +| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. | +| ✅ | [Targeting](#targeting-and-context) | Contextually-aware flag evaluation using [evaluation context](/docs/reference/concepts/evaluation-context). | +| ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. | +| ✅ | [Logging](#logging) | Integrate with popular logging packages. | +| ✅ | [Domains](#domains) | Logically bind clients with providers. | +| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. | +| ✅ | [Tracking](#tracking) | Associate user actions with feature flag evaluations, particularly for A/B testing. | +| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | +| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | +| ✅ | [Multi-Provider](#multi-provider) | Combine multiple providers with configurable evaluation strategies. | Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌ @@ -142,6 +148,57 @@ Once the provider has been registered, the status can be tracked using [events]( In some situations, it may be beneficial to register multiple providers in the same application. This is possible using [domains](#domains), which is covered in more detail below. +#### Multi-Provider + +The Multi-Provider allows you to use multiple underlying providers as sources of flag data for the OpenFeature web SDK. When a flag is being evaluated, the Multi-Provider will consult each underlying provider it is managing in order to determine the final result. Different evaluation strategies can be defined to control which providers get evaluated and which result is used. + +The Multi-Provider is a powerful tool for performing migrations between flag providers, or combining multiple providers into a single feature flagging interface. For example: + +- **Migration**: When migrating between two providers, you can run both in parallel under a unified flagging interface. As flags are added to the new provider, the Multi-Provider will automatically find and return them, falling back to the old provider if the new provider does not have the flag. +- **Multiple Data Sources**: The Multi-Provider allows you to seamlessly combine many sources of flagging data, such as environment variables, local files, database values and SaaS hosted feature management systems. + +```ts +import { MultiProvider } from '@openfeature/web-sdk'; + +const multiProvider = new MultiProvider([{ provider: new ProviderA() }, { provider: new ProviderB() }]); + +await OpenFeature.setProviderAndWait(multiProvider); + +const client = OpenFeature.getClient(); +console.log(client.getBooleanDetails('my-flag', false)); +``` + +By default, the Multi-Provider will evaluate all underlying providers in order and return the first successful result. If a provider indicates it does not have a flag (FLAG_NOT_FOUND error code), then it will be skipped and the next provider will be evaluated. + +##### Evaluation Strategies + +The Multi-Provider comes with three strategies out of the box: + +- **FirstMatchStrategy** (default): Evaluates all providers in order and returns the first successful result. Providers that indicate FLAG_NOT_FOUND error will be skipped and the next provider will be evaluated. +- **FirstSuccessfulStrategy**: Evaluates all providers in order and returns the first successful result. Any error will cause that provider to be skipped. +- **ComparisonStrategy**: Evaluates all providers sequentially. If every provider returns a successful result with the same value, then that result is returned. Otherwise, the result returned by the configured "fallback provider" will be used. + +```ts +import { MultiProvider, FirstSuccessfulStrategy } from '@openfeature/web-sdk'; + +const multiProvider = new MultiProvider( + [{ provider: new ProviderA() }, { provider: new ProviderB() }], + new FirstSuccessfulStrategy(), +); +``` + +##### Tracking Support + +The Multi-Provider supports tracking events across multiple providers, allowing you to send analytics events to all configured providers simultaneously: + +```ts +// Tracked events will be sent to all providers by default +client.track('user-conversion', { + value: 99.99, + currency: 'USD', +}); +``` + ### Flag evaluation flow When a new provider is added to OpenFeature client the following process happens: @@ -173,7 +230,7 @@ Change context after the provider has been registered using `setContext`. ```ts // Set a value to the global context -await OpenFeature.setContext({ targetingKey: localStorage.getItem("targetingKey") }); +await OpenFeature.setContext({ targetingKey: localStorage.getItem('targetingKey') }); ``` Context is global and setting it is `async`. @@ -190,7 +247,7 @@ If the hook you're looking for hasn't been created yet, see the [develop a hook] Once you've added a hook as a dependency, it can be registered at the global, client, or flag invocation level. ```ts -import { OpenFeature } from "@openfeature/web-sdk"; +import { OpenFeature } from '@openfeature/web-sdk'; // add a hook globally, to run on all evaluations OpenFeature.addHooks(new ExampleGlobalHook()); @@ -200,7 +257,7 @@ const client = OpenFeature.getClient(); client.addHooks(new ExampleClientHook()); // add a hook for this evaluation only -const boolValue = client.getBooleanValue("bool-flag", false, { hooks: [new ExampleHook()]}); +const boolValue = client.getBooleanValue('bool-flag', false, { hooks: [new ExampleHook()] }); ``` ### Logging @@ -210,7 +267,7 @@ This behavior can be overridden by passing a custom logger either globally or pe A custom logger must implement the [Logger interface](https://github.com/open-feature/js-sdk/blob/main/packages/shared/src/logger/logger.ts). ```ts -import type { Logger } from "@openfeature/web-sdk"; +import type { Logger } from '@openfeature/web-sdk'; // The logger can be anything that conforms with the Logger interface const logger: Logger = console; @@ -230,17 +287,17 @@ A domain is a logical identifier which can be used to associate clients with a p If a domain has no associated provider, the default provider is used. ```ts -import { OpenFeature, InMemoryProvider } from "@openfeature/web-sdk"; +import { OpenFeature, InMemoryProvider } from '@openfeature/web-sdk'; // Registering the default provider OpenFeature.setProvider(InMemoryProvider(myFlags)); // Registering a provider to a domain -OpenFeature.setProvider("my-domain", new InMemoryProvider(someOtherFlags)); +OpenFeature.setProvider('my-domain', new InMemoryProvider(someOtherFlags)); // A Client bound to the default provider const clientWithDefault = OpenFeature.getClient(); // A Client bound to the InMemoryProvider provider -const domainScopedClient = OpenFeature.getClient("my-domain"); +const domainScopedClient = OpenFeature.getClient('my-domain'); ``` Domains can be defined on a provider during registration. @@ -252,13 +309,13 @@ By default, domain-scoped clients use the global context. This can be overridden by explicitly setting context when registering the provider or by referencing the domain when updating context: ```ts -OpenFeature.setProvider("my-domain", new NewCachedProvider(), { targetingKey: localStorage.getItem("targetingKey") }); +OpenFeature.setProvider('my-domain', new NewCachedProvider(), { targetingKey: localStorage.getItem('targetingKey') }); ``` To change context after the provider has been registered, use `setContext` with a domain: ```ts -await OpenFeature.setContext("my-domain", { targetingKey: localStorage.getItem("targetingKey") }) +await OpenFeature.setContext('my-domain', { targetingKey: localStorage.getItem('targetingKey') }); ``` Once a domain's context has been defined, it will override the global context for all clients bound to the domain. @@ -310,7 +367,7 @@ This should only be called when your application is in the process of shutting d ```ts import { OpenFeature } from '@openfeature/web-sdk'; -await OpenFeature.close() +await OpenFeature.close(); ``` ## Extending @@ -330,7 +387,7 @@ import { Logger, Provider, ProviderEventEmitter, - ResolutionDetails + ResolutionDetails, } from '@openfeature/web-sdk'; // implement the provider interface @@ -342,16 +399,36 @@ class MyProvider implements Provider { } as const; // Optional provider managed hooks hooks?: Hook[]; - resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, context: EvaluationContext, logger: Logger): ResolutionDetails { + resolveBooleanEvaluation( + flagKey: string, + defaultValue: boolean, + context: EvaluationContext, + logger: Logger, + ): ResolutionDetails { // code to evaluate a boolean } - resolveStringEvaluation(flagKey: string, defaultValue: string, context: EvaluationContext, logger: Logger): ResolutionDetails { + resolveStringEvaluation( + flagKey: string, + defaultValue: string, + context: EvaluationContext, + logger: Logger, + ): ResolutionDetails { // code to evaluate a string } - resolveNumberEvaluation(flagKey: string, defaultValue: number, context: EvaluationContext, logger: Logger): ResolutionDetails { + resolveNumberEvaluation( + flagKey: string, + defaultValue: number, + context: EvaluationContext, + logger: Logger, + ): ResolutionDetails { // code to evaluate a number } - resolveObjectEvaluation(flagKey: string, defaultValue: T, context: EvaluationContext, logger: Logger): ResolutionDetails { + resolveObjectEvaluation( + flagKey: string, + defaultValue: T, + context: EvaluationContext, + logger: Logger, + ): ResolutionDetails { // code to evaluate an object } @@ -380,7 +457,7 @@ This can be a new repository or included in [the existing contrib repository](ht Implement your own hook by conforming to the [Hook interface](https://github.com/open-feature/js-sdk/blob/main/packages/shared/src/hooks/hook.ts). ```ts -import type { Hook, HookContext, EvaluationDetails, FlagValue } from "@openfeature/web-sdk"; +import type { Hook, HookContext, EvaluationDetails, FlagValue } from '@openfeature/web-sdk'; export class MyHook implements Hook { after(hookContext: HookContext, evaluationDetails: EvaluationDetails) { diff --git a/docs/reference/technologies/client/web/react.mdx b/docs/reference/sdks/client/web/react.mdx similarity index 76% rename from docs/reference/technologies/client/web/react.mdx rename to docs/reference/sdks/client/web/react.mdx index 09a753ccb..15926712a 100644 --- a/docs/reference/technologies/client/web/react.mdx +++ b/docs/reference/sdks/client/web/react.mdx @@ -10,16 +10,18 @@ This content has been automatically generated from js-sdk. Edits should be made here: https://github.com/open-feature/js-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:20 GMT+0000 (Coordinated Universal Time) --> +import MCPInstall from '@site/src/partials/mcp-install'; +

Specification - - Release + + Release
@@ -33,9 +35,9 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) ## Overview -The OpenFeature React SDK adds React-specific functionality to the [OpenFeature Web SDK](/docs/reference/technologies/client/web). +The OpenFeature React SDK adds React-specific functionality to the [OpenFeature Web SDK](/docs/reference/sdks/client/web). -In addition to the feature provided by the [web sdk](/docs/reference/technologies/client/web), capabilities include: +In addition to the feature provided by the [web sdk](/docs/reference/sdks/client/web), capabilities include: - [Overview](#overview) - [Quick start](#quick-start) @@ -47,17 +49,23 @@ In addition to the feature provided by the [web sdk](/docs/reference/technologie - [Usage](#usage) - [OpenFeatureProvider context provider](#openfeatureprovider-context-provider) - [Evaluation hooks](#evaluation-hooks) + - [Declarative components](#declarative-components) + - [FeatureFlag Component](#featureflag-component) - [Multiple Providers and Domains](#multiple-providers-and-domains) - [Re-rendering with Context Changes](#re-rendering-with-context-changes) - [Re-rendering with Flag Configuration Changes](#re-rendering-with-flag-configuration-changes) - [Suspense Support](#suspense-support) - [Tracking](#tracking) + - [Observability Considerations](#observability-considerations) - [Testing](#testing) - [FAQ and troubleshooting](#faq-and-troubleshooting) - [Resources](#resources) ## Quick start + + + ### Requirements - ES2015-compatible web browser (Chrome, Edge, Firefox, etc) @@ -83,8 +91,8 @@ yarn add @openfeature/react-sdk @openfeature/web-sdk @openfeature/core The following list contains the peer dependencies of `@openfeature/react-sdk`. See the [package.json](https://github.com/open-feature/js-sdk/blob/main/packages/react/package.json) for the required versions. -* `@openfeature/web-sdk` -* `react` +- `@openfeature/web-sdk` +- `react` ### Usage @@ -104,13 +112,13 @@ const flagConfig = { on: true, off: false, }, - defaultVariant: "on", + defaultVariant: 'on', contextEvaluator: (context: EvaluationContext) => { if (context.silly) { return 'on'; } - return 'off' - } + return 'off'; + }, }, }; @@ -142,7 +150,7 @@ function Page() { {showNewMessage ?

Welcome to this OpenFeature-enabled React app!

:

Welcome to this React app.

} - ) + ); } ``` @@ -159,14 +167,71 @@ const value = useBooleanFlagValue('new-message', false); import { useBooleanFlagDetails } from '@openfeature/react-sdk'; // "detailed" boolean flag evaluation -const { - value, - variant, - reason, - flagMetadata -} = useBooleanFlagDetails('new-message', false); +const { value, variant, reason, flagMetadata } = useBooleanFlagDetails('new-message', false); ``` +#### Declarative components + +The React SDK includes declarative components for feature flagging that provide a more JSX-native approach to conditional rendering. + +##### FeatureFlag Component + +The `FeatureFlag` component conditionally renders its children based on feature flag evaluation: + +```tsx +import { FeatureFlag } from '@openfeature/react-sdk'; + +function App() { + return ( + + {/* Basic usage - renders children when flag is truthy */} + + + + + {/* Match specific values */} + + + + + {/* Boolean flag with fallback */} + }> + + + + {/* Custom predicate function for complex matching */} + !!expected && actual.value.includes(expected)} + > + + + + {/* Function as children for accessing flag details */} + + {({ value, reason }) => ( + + value is {value}, reason is {reason?.toString()} + + )} + + + ); +} +``` + +The `FeatureFlag` component supports the following props: + +- **`flagKey`** (required): The feature flag key to evaluate +- **`defaultValue`** (required): Default value when the flag is not available +- **`matchValue`** (required, except for boolean flags): Value to match against the flag value. By default, an optimized deep-comparison function is used. +- **`predicate`** (optional): Custom function for matching logic that receives the expected value and evaluation details +- **`children`**: Content to render when condition is met (can be JSX or a function receiving flag details) +- **`fallback`** (optional): Content to render when condition is not met + #### Multiple Providers and Domains Multiple providers can be used by passing a `domain` to the `OpenFeatureProvider`: @@ -283,7 +348,7 @@ This can be disabled in the hook options (or in the [OpenFeatureProvider](#openf The tracking API allows you to use OpenFeature abstractions and objects to associate user actions with feature flag evaluations. This is essential for robust experimentation powered by feature flags. -For example, a flag enhancing the appearance of a UI component might drive user engagement to a new feature; to test this hypothesis, telemetry collected by a [hook](/docs/reference/technologies/client/web/#hooks) or [provider](/docs/reference/technologies/client/web/#providers) can be associated with telemetry reported in the client's `track` function. +For example, a flag enhancing the appearance of a UI component might drive user engagement to a new feature; to test this hypothesis, telemetry collected by a [hook](/docs/reference/sdks/client/web/#hooks) or [provider](/docs/reference/sdks/client/web/#providers) can be associated with telemetry reported in the client's `track` function. The React SDK includes a hook for firing tracking events in the `` context in use: @@ -300,11 +365,17 @@ function MyComponent() { } ``` +#### Observability Considerations + +React's lifecycle can result in flags being evaluated multiple times as a user interacts with a page. +If you are using an OpenFeature hook for telemetry, this can result in inflated evaluation metrics. +The [OpenFeature debounce hook](https://github.com/open-feature/js-sdk-contrib/tree/main/libs/hooks/debounce) can help to reduce the amount of redundant evaluations reported to your observability platform by limiting the frequency at which evaluation metrics are reported. + ### Testing The React SDK includes a built-in context provider for testing. -This allows you to easily test components that use evaluation hooks, such as `useFlag`. -If you try to test a component (in this case, `MyComponent`) which uses an evaluation hook, you might see an error message like: +This allows you to easily test components that use evaluation hooks (such as `useFlag`) or declarative components (such as `FeatureFlag`). +If you try to test a component (in this case, `MyComponent`) which uses feature flags, you might see an error message like: > No OpenFeature client available - components using OpenFeature must be wrapped with an ``. @@ -325,6 +396,16 @@ If you'd like to control the values returned by the evaluation hooks, you can pa + +// testing declarative FeatureFlag components + + + + + + + + ``` Additionally, you can pass an artificial delay for the provider startup to test your suspense boundaries or loaders/spinners impacted by feature flags: @@ -396,4 +477,4 @@ Avoid importing anything from `@openfeature/web-sdk` or `@openfeature/core`. ## Resources - - [Example repo](https://github.com/open-feature/react-test-app) +- [Example repo](https://github.com/open-feature/react-test-app) diff --git a/docs/reference/technologies/index.mdx b/docs/reference/sdks/index.mdx similarity index 89% rename from docs/reference/technologies/index.mdx rename to docs/reference/sdks/index.mdx index 3ed231b8c..28f94772d 100644 --- a/docs/reference/technologies/index.mdx +++ b/docs/reference/sdks/index.mdx @@ -1,10 +1,10 @@ --- sidebar_position: 2 -id: technologies -title: Technologies +id: sdks +title: SDK Technologies --- -# Technologies +# SDK Technologies OpenFeature SDKs and components for a range of supported languages and runtimes. diff --git a/docs/reference/technologies/sdk-compatibility.mdx b/docs/reference/sdks/sdk-compatibility.mdx similarity index 100% rename from docs/reference/technologies/sdk-compatibility.mdx rename to docs/reference/sdks/sdk-compatibility.mdx diff --git a/docs/reference/technologies/client/_category_.json b/docs/reference/sdks/server/_category_.json similarity index 100% rename from docs/reference/technologies/client/_category_.json rename to docs/reference/sdks/server/_category_.json diff --git a/docs/reference/technologies/server/dart.mdx b/docs/reference/sdks/server/dart.mdx similarity index 97% rename from docs/reference/technologies/server/dart.mdx rename to docs/reference/sdks/server/dart.mdx index 4734b37e3..43d07a39b 100644 --- a/docs/reference/technologies/server/dart.mdx +++ b/docs/reference/sdks/server/dart.mdx @@ -9,7 +9,7 @@ This content has been automatically generated from dart-server-sdk. Edits should be made here: https://github.com/open-feature/dart-server-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:20 GMT+0000 (Coordinated Universal Time) -->

@@ -19,8 +19,8 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) - - Release + + Release @@ -56,7 +56,7 @@ Dart language version: [3.9.2](https://dart.dev/get-dart/archive) ```yaml dependencies: - openfeature_dart_server_sdk: ^0.0.13 + openfeature_dart_server_sdk: ^0.0.16 ``` ### Then run: @@ -69,26 +69,21 @@ dart pub get ```dart import 'dart:async'; -import 'package:openfeature_dart_server_sdk/client.dart'; import 'package:openfeature_dart_server_sdk/open_feature_api.dart'; import 'package:openfeature_dart_server_sdk/feature_provider.dart'; -import 'package:openfeature_dart_server_sdk/evaluation_context.dart'; -import 'package:openfeature_dart_server_sdk/hooks.dart'; void main() async { - // Register your feature flag provider + // Get the API instance final api = OpenFeatureAPI(); - api.setProvider(InMemoryProvider({ + + // Register your feature flag provider and wait for it to be ready + await api.setProviderAndWait(InMemoryProvider({ 'new-feature': true, 'welcome-message': 'Hello, OpenFeature!' })); // Create a client - final client = FeatureClient( - metadata: ClientMetadata(name: 'my-app'), - hookManager: HookManager(), - defaultContext: EvaluationContext(attributes: {}), - ); + final client = api.getClient('my-app'); // Evaluate your feature flags final newFeatureEnabled = await client.getBooleanFlag( @@ -96,6 +91,13 @@ void main() async { defaultValue: false, ); + // Get full evaluation details if needed + final details = await client.getBooleanDetails( + 'new-feature', + defaultValue: false, + ); + print('Reason: ${details.reason}, Variant: ${details.variant}'); + // Use the returned flag value if (newFeatureEnabled) { print('New feature is enabled!'); diff --git a/docs/reference/technologies/server/dotnet.mdx b/docs/reference/sdks/server/dotnet.mdx similarity index 97% rename from docs/reference/technologies/server/dotnet.mdx rename to docs/reference/sdks/server/dotnet.mdx index 225d25dd4..026213d75 100644 --- a/docs/reference/technologies/server/dotnet.mdx +++ b/docs/reference/sdks/server/dotnet.mdx @@ -10,13 +10,15 @@ This content has been automatically generated from dotnet-sdk. Edits should be made here: https://github.com/open-feature/dotnet-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:19 GMT+0000 (Coordinated Universal Time) --> +import MCPInstall from '@site/src/partials/mcp-install'; + [![Specification](https://img.shields.io/static/v1?label=specification&message=v0.8.0&color=yellow&style=for-the-badge)](https://github.com/open-feature/spec/releases/tag/v0.8.0) [ -![Release](https://img.shields.io/static/v1?label=release&message=v2.8.1&color=blue&style=for-the-badge) -](https://github.com/open-feature/dotnet-sdk/releases/tag/v2.8.1) +![Release](https://img.shields.io/static/v1?label=release&message=v2.11.1&color=blue&style=for-the-badge) +](https://github.com/open-feature/dotnet-sdk/releases/tag/v2.11.1) [![Slack](https://img.shields.io/badge/slack-%40cncf%2Fopenfeature-brightgreen?style=flat&logo=slack)](https://cloud-native.slack.com/archives/C0344AANLA1) [![Codecov](https://codecov.io/gh/open-feature/dotnet-sdk/branch/main/graph/badge.svg?token=MONAVJBXUJ)](https://codecov.io/gh/open-feature/dotnet-sdk) @@ -25,6 +27,9 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) ## Quick start + + + ### Requirements - .NET 8+ @@ -442,10 +447,12 @@ Built a new hook? [Let us know](https://github.com/open-feature/openfeature.dev/ ### Multi-Provider > [!NOTE] -> The Multi-Provider feature is currently experimental. Hooks and events are not supported at the moment. +> The Multi-Provider feature is currently experimental. The Multi-Provider enables the use of multiple underlying feature flag providers simultaneously, allowing different providers to be used for different flag keys or based on specific evaluation strategies. +The Multi-Provider supports provider hooks and executes them in accordance with the OpenFeature specification. Each provider's hooks are executed with context isolation, ensuring that context modifications by one provider's hooks do not affect other providers. + #### Basic Usage ```csharp @@ -523,23 +530,20 @@ The Multi-Provider supports two evaluation modes: #### Limitations -- **Hooks are not supported**: Multi-Provider does not currently support hook registration or execution -- **Events are not supported**: Provider events are not propagated from underlying providers -- **Experimental status**: The API may change in future releases +- **Experimental status**: The API may change in future releases For a complete example, see the [AspNetCore sample](https://github.com/open-feature/dotnet-sdk/blob/main/samples/AspNetCore/README.md) which demonstrates Multi-Provider usage. ### Dependency Injection > [!NOTE] -> The OpenFeature.DependencyInjection and OpenFeature.Hosting packages are currently experimental. They streamline the integration of OpenFeature within .NET applications, allowing for seamless configuration and lifecycle management of feature flag providers using dependency injection and hosting services. +> The OpenFeature.Hosting package is currently experimental. The Hosting package streamlines the integration of OpenFeature within .NET applications, allowing for seamless configuration and lifecycle management of feature flag providers using dependency injection and hosting services. #### Installation -To set up dependency injection and hosting capabilities for OpenFeature, install the following packages: +To set up dependency injection and hosting capabilities for OpenFeature, install the following package: ```sh -dotnet add package OpenFeature.DependencyInjection dotnet add package OpenFeature.Hosting ``` @@ -552,7 +556,6 @@ For a basic configuration, you can use the InMemoryProvider. This provider is si ```csharp builder.Services.AddOpenFeature(featureBuilder => { featureBuilder - .AddHostedFeatureLifecycle() // From Hosting package .AddInMemoryProvider(); }); ``` @@ -574,7 +577,6 @@ builder.Services.AddOpenFeature(featureBuilder => { ```csharp builder.Services.AddOpenFeature(featureBuilder => { featureBuilder - .AddHostedFeatureLifecycle() .AddContext((contextBuilder, serviceProvider) => { /* Custom context configuration */ }) .AddHook((serviceProvider) => new LoggingHook( /* Custom configuration */ )) .AddHook(new MetricsHook()) diff --git a/docs/reference/technologies/server/go.mdx b/docs/reference/sdks/server/go.mdx similarity index 97% rename from docs/reference/technologies/server/go.mdx rename to docs/reference/sdks/server/go.mdx index dcedcaf92..fd13494c5 100644 --- a/docs/reference/technologies/server/go.mdx +++ b/docs/reference/sdks/server/go.mdx @@ -9,16 +9,18 @@ This content has been automatically generated from go-sdk. Edits should be made here: https://github.com/open-feature/go-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:19 GMT+0000 (Coordinated Universal Time) --> +import MCPInstall from '@site/src/partials/mcp-install'; +

Specification - - Release + + Release
@@ -38,6 +40,9 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) ## Quick start + + + ### Requirements Go language version: [1.24](https://go.dev/doc/devel/release#go1.24.0) @@ -114,7 +119,8 @@ openfeature.SetProviderAndWait(MyProvider{}) ``` In some situations, it may be beneficial to register multiple providers in the same application. -This is possible using [domains](#domains), which is covered in more details below. +This is possible using [domains](#domains), which is covered in more details below, or the included [multiprovider](#multi-provider-implementation) +implementation. ### Targeting @@ -326,6 +332,11 @@ tCtx := openfeature.MergeTransactionContext(ctx, openfeature.EvaluationContext{} client.BooleanValue(tCtx, ....) ``` +### Multi-Provider Implementation + +Included with this SDK is an _experimental_ multi-provider that can be used to query multiple feature flag providers simultaneously. +More information can be found in the [multi package's README](https://github.com/open-feature/go-sdk/blob/main/openfeature/multi/README.md). + ## Extending ### Develop a provider diff --git a/docs/reference/technologies/server/index.mdx b/docs/reference/sdks/server/index.mdx similarity index 100% rename from docs/reference/technologies/server/index.mdx rename to docs/reference/sdks/server/index.mdx diff --git a/docs/reference/technologies/server/java.mdx b/docs/reference/sdks/server/java.mdx similarity index 91% rename from docs/reference/technologies/server/java.mdx rename to docs/reference/sdks/server/java.mdx index f73a345a5..9bd44a3a7 100644 --- a/docs/reference/technologies/server/java.mdx +++ b/docs/reference/sdks/server/java.mdx @@ -9,8 +9,10 @@ This content has been automatically generated from java-sdk. Edits should be made here: https://github.com/open-feature/java-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:44 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:19 GMT+0000 (Coordinated Universal Time) --> +import MCPInstall from '@site/src/partials/mcp-install'; +

@@ -18,8 +20,8 @@ Last updated at Mon Oct 06 2025 08:10:44 GMT+0000 (Coordinated Universal Time) - - Release + + Release @@ -40,6 +42,9 @@ Last updated at Mon Oct 06 2025 08:10:44 GMT+0000 (Coordinated Universal Time) ## Quick start + + + ### Requirements - Java 11+ (compiler target is 11) @@ -54,7 +59,7 @@ Note that this library is intended to be used in server-side contexts and has no dev.openfeature sdk - 1.18.1 + 1.20.1 ``` @@ -77,7 +82,7 @@ If you would like snapshot builds, this is the relevant repository information: ```groovy dependencies { - implementation 'dev.openfeature:sdk:1.18.1' + implementation 'dev.openfeature:sdk:1.20.1' } ``` @@ -121,6 +126,7 @@ See [here](https://javadoc.io/doc/dev.openfeature/sdk/latest/) for the Javadocs. | ------ |---------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------| | ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. | | ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](/docs/reference/concepts/evaluation-context). | +| ✅ | [Multi-provider (experimental)](#multi-provider-experimental) | Combine multiple providers and delegate evaluations according to a strategy. | | ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. | | ✅ | [Tracking](#tracking) | Associate user actions with feature flag evaluations. | | ✅ | [Logging](#logging) | Integrate with popular logging packages. | @@ -139,7 +145,39 @@ Look [here](/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Provi If the provider you're looking for hasn't been created yet, see the [develop a provider](#develop-a-provider) section to learn how to build it yourself. Once you've added a provider as a dependency, it can be registered with OpenFeature like this: - + +In some situations, it may be beneficial to register multiple providers in the same application. +This is possible using [domains](#domains), which is covered in more detail below. + +#### Multi-provider (experimental) + +In addition to domains, you may want to delegate flag evaluation across multiple providers using a configurable strategy. +The multi-provider allows you to compose several `FeatureProvider` implementations and determine which provider's result to use. + +> **Experimental:** This API is experimental and may change in future releases. + +```java +import dev.openfeature.sdk.OpenFeatureAPI; +import dev.openfeature.sdk.Client; +import dev.openfeature.sdk.FeatureProvider; +import dev.openfeature.sdk.multiprovider.MultiProvider; + +import java.util.List; + +public void multiProviderExample() throws Exception { + FeatureProvider primaryProvider = new MyPrimaryProvider(); + FeatureProvider fallbackProvider = new MyFallbackProvider(); + + MultiProvider multiProvider = new MultiProvider(List.of(primaryProvider, fallbackProvider)); + + OpenFeatureAPI api = OpenFeatureAPI.getInstance(); + api.setProviderAndWait(multiProvider); + + Client client = api.getClient(); + boolean value = client.getBooleanValue("some-flag", false); +} +``` + #### Synchronous To register a provider in a blocking manner to ensure it is ready before further actions are taken, you can use the `setProviderAndWait` method as shown below: diff --git a/docs/reference/technologies/server/javascript/_category_.json b/docs/reference/sdks/server/javascript/_category_.json similarity index 100% rename from docs/reference/technologies/server/javascript/_category_.json rename to docs/reference/sdks/server/javascript/_category_.json diff --git a/docs/reference/technologies/server/javascript/index.mdx b/docs/reference/sdks/server/javascript/index.mdx similarity index 67% rename from docs/reference/technologies/server/javascript/index.mdx rename to docs/reference/sdks/server/javascript/index.mdx index 6f3cd47f3..7448dc547 100644 --- a/docs/reference/technologies/server/javascript/index.mdx +++ b/docs/reference/sdks/server/javascript/index.mdx @@ -10,16 +10,18 @@ This content has been automatically generated from js-sdk. Edits should be made here: https://github.com/open-feature/js-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:44 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:19 GMT+0000 (Coordinated Universal Time) --> +import MCPInstall from '@site/src/partials/mcp-install'; +

Specification - - Release + + Release
@@ -39,6 +41,9 @@ Last updated at Mon Oct 06 2025 08:10:44 GMT+0000 (Coordinated Universal Time) ## Quick start + + + ### Requirements - Node.js version 18+ @@ -52,7 +57,7 @@ npm install --save @openfeature/server-sdk ``` > [!TIP] -> This SDK is designed to run in Node.JS. If you're interested in browser support, check out the [Web SDK](/docs/reference/technologies/client/web/). +> This SDK is designed to run in Node.JS. If you're interested in browser support, check out the [Web SDK](/docs/reference/sdks/client/web/). #### yarn @@ -85,7 +90,7 @@ const client = OpenFeature.getClient(); const v2Enabled = await client.getBooleanValue('v2_enabled', false); if (v2Enabled) { - console.log("v2 is enabled"); + console.log('v2 is enabled'); } ``` @@ -95,18 +100,19 @@ See [here](https://open-feature.github.io/js-sdk/modules/_openfeature_server_sdk ## Features -| Status | Features | Description | -| ------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. | -| ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](/docs/reference/concepts/evaluation-context). | -| ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. | -| ✅ | [Logging](#logging) | Integrate with popular logging packages. | -| ✅ | [Domains](#domains) | Logically bind clients with providers. | -| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. | -| ✅ | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread) | -| ✅ | [Tracking](#tracking) | Associate user actions with feature flag evaluations, particularly for A/B testing. | -| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | -| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | +| Status | Features | Description | +| ------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. | +| ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](/docs/reference/concepts/evaluation-context). | +| ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. | +| ✅ | [Logging](#logging) | Integrate with popular logging packages. | +| ✅ | [Domains](#domains) | Logically bind clients with providers. | +| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. | +| ✅ | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread) | +| ✅ | [Tracking](#tracking) | Associate user actions with feature flag evaluations, particularly for A/B testing. | +| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | +| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | +| ✅ | [Multi-Provider](#multi-provider) | Combine multiple providers with configurable evaluation strategies. | Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌ @@ -137,7 +143,77 @@ OpenFeature.setProvider(new MyProvider()); Once the provider has been registered, the status can be tracked using [events](#eventing). In some situations, it may be beneficial to register multiple providers in the same application. -This is possible using [domains](#domains), which is covered in more details below. +This is possible using [domains](#domains), which is covered in more detail below. + +#### Multi-Provider + +The Multi-Provider allows you to use multiple underlying providers as sources of flag data for the OpenFeature server SDK. When a flag is being evaluated, the Multi-Provider will consult each underlying provider it is managing in order to determine the final result. Different evaluation strategies can be defined to control which providers get evaluated and which result is used. + +The Multi-Provider is a powerful tool for performing migrations between flag providers, or combining multiple providers into a single feature flagging interface. For example: + +- **Migration**: Gradually migrate from one provider to another by serving some flags from your old provider and some from your new provider +- **Backup**: Use one provider as a backup for another in case of failures +- **Comparison**: Compare results from multiple providers to validate consistency +- **Hybrid**: Combine multiple providers to leverage different strengths (e.g., one for simple flags, another for complex targeting) + +```ts +import { OpenFeature, MultiProvider, FirstMatchStrategy } from '@openfeature/server-sdk'; + +// Create providers +const primaryProvider = new YourPrimaryProvider(); +const backupProvider = new YourBackupProvider(); + +// Create multi-provider with a strategy +const multiProvider = new MultiProvider([primaryProvider, backupProvider], new FirstMatchStrategy()); + +// Register the multi-provider +await OpenFeature.setProviderAndWait(multiProvider); + +// Use as normal +const client = OpenFeature.getClient(); +const value = await client.getBooleanValue('my-flag', false); +``` + +**Available Strategies:** + +- `FirstMatchStrategy`: Returns the first successful result from the list of providers +- `ComparisonStrategy`: Compares results from multiple providers and can handle discrepancies + +**Migration Example:** + +```ts +import { OpenFeature, MultiProvider, FirstMatchStrategy } from '@openfeature/server-sdk'; + +// During migration, serve some flags from the new provider and fallback to the old one +const newProvider = new NewFlagProvider(); +const oldProvider = new OldFlagProvider(); + +const multiProvider = new MultiProvider( + [newProvider, oldProvider], // New provider is consulted first + new FirstMatchStrategy(), +); + +await OpenFeature.setProviderAndWait(multiProvider); +``` + +**Comparison Example:** + +```ts +import { OpenFeature, MultiProvider, ComparisonStrategy } from '@openfeature/server-sdk'; + +// Compare results from two providers for validation +const providerA = new ProviderA(); +const providerB = new ProviderB(); + +const multiProvider = new MultiProvider( + [{ provider: providerA }, { provider: providerB }], + new ComparisonStrategy(providerA, (resolutions) => { + console.warn('Mismatch detected', resolutions); + }), +); + +await OpenFeature.setProviderAndWait(multiProvider); +``` ### Targeting @@ -147,7 +223,7 @@ If the flag management system you're using supports targeting, you can provide t ```ts // set a value to the global context -OpenFeature.setContext({ region: "us-east-1" }); +OpenFeature.setContext({ region: 'us-east-1' }); // set a value to the client context const client = OpenFeature.getClient(); @@ -157,7 +233,7 @@ client.setContext({ version: process.env.APP_VERSION }); const requestContext = { targetingKey: req.session.id, email: req.session.email, - product: req.productId + product: req.productId, }; const boolValue = await client.getBooleanValue('some-flag', false, requestContext); @@ -175,7 +251,7 @@ If the hook you're looking for hasn't been created yet, see the [develop a hook] Once you've added a hook as a dependency, it can be registered at the global, client, or flag invocation level. ```ts -import { OpenFeature } from "@openfeature/server-sdk"; +import { OpenFeature } from '@openfeature/server-sdk'; // add a hook globally, to run on all evaluations OpenFeature.addHooks(new ExampleGlobalHook()); @@ -185,7 +261,7 @@ const client = OpenFeature.getClient(); client.addHooks(new ExampleClientHook()); // add a hook for this evaluation only -const boolValue = await client.getBooleanValue("bool-flag", false, { hooks: [new ExampleHook()]}); +const boolValue = await client.getBooleanValue('bool-flag', false, { hooks: [new ExampleHook()] }); ``` ### Logging @@ -195,7 +271,7 @@ This behavior can be overridden by passing a custom logger either globally or pe A custom logger must implement the [Logger interface](https://github.com/open-feature/js-sdk/blob/main/packages/shared/src/logger/logger.ts). ```ts -import type { Logger } from "@openfeature/server-sdk"; +import type { Logger } from '@openfeature/server-sdk'; // The logger can be anything that conforms with the Logger interface const logger: Logger = console; @@ -215,28 +291,28 @@ A domain is a logical identifier which can be used to associate clients with a p If a domain has no associated provider, the default provider is used. ```ts -import { OpenFeature, InMemoryProvider } from "@openfeature/server-sdk"; +import { OpenFeature, InMemoryProvider } from '@openfeature/server-sdk'; const myFlags = { - 'v2_enabled': { + v2_enabled: { variants: { on: true, - off: false + off: false, }, disabled: false, - defaultVariant: "on" - } + defaultVariant: 'on', + }, }; // Registering the default provider OpenFeature.setProvider(InMemoryProvider(myFlags)); // Registering a provider to a domain -OpenFeature.setProvider("my-domain", new InMemoryProvider(someOtherFlags)); +OpenFeature.setProvider('my-domain', new InMemoryProvider(someOtherFlags)); // A Client bound to the default provider const clientWithDefault = OpenFeature.getClient(); // A Client bound to the InMemoryProvider provider -const domainScopedClient = OpenFeature.getClient("my-domain"); +const domainScopedClient = OpenFeature.getClient('my-domain'); ``` Domains can be defined on a provider during registration. @@ -273,22 +349,22 @@ Transaction context can be set where specific data is available (e.g. an auth se The following example shows an Express middleware using transaction context propagation to propagate the request ip and user id into request scoped transaction context. ```ts -import express, { Request, Response, NextFunction } from "express"; +import express, { Request, Response, NextFunction } from 'express'; import { OpenFeature, AsyncLocalStorageTransactionContextPropagator } from '@openfeature/server-sdk'; -OpenFeature.setTransactionContextPropagator(new AsyncLocalStorageTransactionContextPropagator()) +OpenFeature.setTransactionContextPropagator(new AsyncLocalStorageTransactionContextPropagator()); /** * This example is based on an express middleware. */ const app = express(); app.use((req: Request, res: Response, next: NextFunction) => { - const ip = res.headers.get("X-Forwarded-For") + const ip = res.headers.get('X-Forwarded-For'); OpenFeature.setTransactionContext({ targetingKey: req.user.id, ipAddress: ip }, () => { // The transaction context is used in any flag evaluation throughout the whole call chain of next next(); }); -}) +}); ``` ### Tracking @@ -314,7 +390,7 @@ This should only be called when your application is in the process of shutting d ```ts import { OpenFeature } from '@openfeature/server-sdk'; -await OpenFeature.close() +await OpenFeature.close(); ``` ## Extending @@ -334,7 +410,7 @@ import { Logger, Provider, ProviderEventEmitter, - ResolutionDetails + ResolutionDetails, } from '@openfeature/server-sdk'; // implement the provider interface @@ -346,16 +422,36 @@ class MyProvider implements Provider { } as const; // Optional provider managed hooks hooks?: Hook[]; - resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, context: EvaluationContext, logger: Logger): Promise> { + resolveBooleanEvaluation( + flagKey: string, + defaultValue: boolean, + context: EvaluationContext, + logger: Logger, + ): Promise> { // code to evaluate a boolean } - resolveStringEvaluation(flagKey: string, defaultValue: string, context: EvaluationContext, logger: Logger): Promise> { + resolveStringEvaluation( + flagKey: string, + defaultValue: string, + context: EvaluationContext, + logger: Logger, + ): Promise> { // code to evaluate a string } - resolveNumberEvaluation(flagKey: string, defaultValue: number, context: EvaluationContext, logger: Logger): Promise> { + resolveNumberEvaluation( + flagKey: string, + defaultValue: number, + context: EvaluationContext, + logger: Logger, + ): Promise> { // code to evaluate a number } - resolveObjectEvaluation(flagKey: string, defaultValue: T, context: EvaluationContext, logger: Logger): Promise> { + resolveObjectEvaluation( + flagKey: string, + defaultValue: T, + context: EvaluationContext, + logger: Logger, + ): Promise> { // code to evaluate an object } @@ -380,7 +476,7 @@ This can be a new repository or included in [the existing contrib repository](ht Implement your own hook by conforming to the [Hook interface](https://github.com/open-feature/js-sdk/blob/main/packages/shared/src/hooks/hook.ts). ```ts -import type { Hook, HookContext, EvaluationDetails, FlagValue } from "@openfeature/server-sdk"; +import type { Hook, HookContext, EvaluationDetails, FlagValue } from '@openfeature/server-sdk'; export class MyHook implements Hook { after(hookContext: HookContext, evaluationDetails: EvaluationDetails) { diff --git a/docs/reference/technologies/server/javascript/nestjs.mdx b/docs/reference/sdks/server/javascript/nestjs.mdx similarity index 96% rename from docs/reference/technologies/server/javascript/nestjs.mdx rename to docs/reference/sdks/server/javascript/nestjs.mdx index e93b603d3..5d4606f61 100644 --- a/docs/reference/technologies/server/javascript/nestjs.mdx +++ b/docs/reference/sdks/server/javascript/nestjs.mdx @@ -10,8 +10,10 @@ This content has been automatically generated from js-sdk. Edits should be made here: https://github.com/open-feature/js-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:19 GMT+0000 (Coordinated Universal Time) --> +import MCPInstall from '@site/src/partials/mcp-install'; +

@@ -33,7 +35,7 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) ## Overview -The OpenFeature NestJS SDK is a package that provides a NestJS wrapper for the [OpenFeature Server SDK](/docs/reference/technologies/server/javascript/). +The OpenFeature NestJS SDK is a package that provides a NestJS wrapper for the [OpenFeature Server SDK](/docs/reference/sdks/server/javascript/). Capabilities include: @@ -45,6 +47,9 @@ Capabilities include: ## Quick start + + + ### Requirements - Node.js version 20+ diff --git a/docs/reference/technologies/server/php.mdx b/docs/reference/sdks/server/php.mdx similarity index 98% rename from docs/reference/technologies/server/php.mdx rename to docs/reference/sdks/server/php.mdx index 45e72ea7b..beaf8aeec 100644 --- a/docs/reference/technologies/server/php.mdx +++ b/docs/reference/sdks/server/php.mdx @@ -9,8 +9,10 @@ This content has been automatically generated from php-sdk. Edits should be made here: https://github.com/open-feature/php-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:19 GMT+0000 (Coordinated Universal Time) --> +import MCPInstall from '@site/src/partials/mcp-install'; +

@@ -19,8 +21,8 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) - - Release + + Release @@ -46,6 +48,9 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) ## Quick start + + + ### Requirements This library targets PHP version 8.0 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. diff --git a/docs/reference/technologies/server/python.mdx b/docs/reference/sdks/server/python.mdx similarity index 98% rename from docs/reference/technologies/server/python.mdx rename to docs/reference/sdks/server/python.mdx index f39a79d5f..328394dde 100644 --- a/docs/reference/technologies/server/python.mdx +++ b/docs/reference/sdks/server/python.mdx @@ -9,8 +9,10 @@ This content has been automatically generated from python-sdk. Edits should be made here: https://github.com/open-feature/python-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:19 GMT+0000 (Coordinated Universal Time) --> +import MCPInstall from '@site/src/partials/mcp-install'; +

@@ -20,8 +22,8 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) - - Latest version + + Latest version @@ -35,7 +37,7 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) - Min python version + Min python version @@ -45,22 +47,25 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) ## Quick start + + + ### Requirements -- Python 3.9+ +- Python 3.10+ ### Install #### Pip install ```bash -pip install openfeature-sdk==0.8.3 +pip install openfeature-sdk==0.8.4 ``` #### requirements.txt ```bash -openfeature-sdk==0.8.3 +openfeature-sdk==0.8.4 ``` ```python diff --git a/docs/reference/technologies/server/ruby.mdx b/docs/reference/sdks/server/ruby.mdx similarity index 80% rename from docs/reference/technologies/server/ruby.mdx rename to docs/reference/sdks/server/ruby.mdx index 8ea111140..ceb45c36a 100644 --- a/docs/reference/technologies/server/ruby.mdx +++ b/docs/reference/sdks/server/ruby.mdx @@ -10,8 +10,10 @@ This content has been automatically generated from ruby-sdk. Edits should be made here: https://github.com/open-feature/ruby-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:20 GMT+0000 (Coordinated Universal Time) --> +import MCPInstall from '@site/src/partials/mcp-install'; +

@@ -19,8 +21,8 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) - - Release + + Release @@ -32,6 +34,9 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) ## Quick start + + + ### Requirements | Supported Ruby Version | OS | @@ -102,7 +107,7 @@ object = client.fetch_object_value(flag_key: 'object_value', default_value: { na | ⚠️ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. | | ❌ | [Logging](#logging) | Integrate with popular logging packages. | | ✅ | [Domains](#domains) | Logically bind clients with providers. | -| ❌ | [Eventing](#eventing) | React to state changes in the provider or flag management system. | +| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. | | ⚠️ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | | ❌ | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread) | | ⚠️ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | @@ -128,6 +133,45 @@ OpenFeature::SDK.configure do |config| end ``` +#### Blocking Provider Registration + +If you need to ensure that a provider is fully initialized before continuing, you can use `set_provider_and_wait`: + +```ruby +# Using the SDK directly +begin + OpenFeature::SDK.set_provider_and_wait(my_provider) + puts "Provider is ready!" +rescue OpenFeature::SDK::ProviderInitializationError => e + puts "Provider failed to initialize: #{e.message}" + puts "Error code: #{e.error_code}" + # original_error contains the underlying exception that caused the initialization failure + puts "Original error: #{e.original_error}" +end + +# With custom timeout (default is 30 seconds) +OpenFeature::SDK.set_provider_and_wait(my_provider, timeout: 60) + +# Domain-specific provider +OpenFeature::SDK.set_provider_and_wait(my_provider, domain: "feature-flags") + +# Via configuration block +OpenFeature::SDK.configure do |config| + begin + config.set_provider_and_wait(my_provider) + rescue OpenFeature::SDK::ProviderInitializationError => e + # Handle initialization failure + end +end +``` + +The `set_provider_and_wait` method: +- Waits for the provider's `init` method to complete successfully +- Raises `ProviderInitializationError` if initialization fails or times out +- Provides access to the provider instance, error code, and original exception for debugging +- The `original_error` field contains the underlying exception that caused the initialization failure +- Uses the same thread-safe provider switching as `set_provider` + In some situations, it may be beneficial to register multiple providers in the same application. This is possible using [domains](#domains), which is covered in more detail below. @@ -188,13 +232,47 @@ legacy_flag_client = OpenFeature::SDK.build_client(domain: "legacy_flags") ### Eventing -Coming Soon! [Issue available](https://github.com/open-feature/ruby-sdk/issues/51) to be worked on. - - +Please refer to the documentation of the provider you're using to see what events are supported. + +```ruby +# Register event handlers at the API (global) level +ready_handler = ->(event_details) do + puts "Provider #{event_details[:provider].metadata.name} is ready!" +end + +OpenFeature::SDK.add_handler(OpenFeature::SDK::ProviderEvent::PROVIDER_READY, ready_handler) + +# The SDK automatically emits lifecycle events. Providers can emit additional spontaneous events +# using the EventEmitter mixin to signal internal state changes like configuration updates. +class MyEventAwareProvider + include OpenFeature::SDK::Provider::EventEmitter + + def init(evaluation_context) + # Start background process to monitor for configuration changes + # Note: SDK automatically emits PROVIDER_READY when init completes successfully + start_background_process + end + + def start_background_process + Thread.new do + # Monitor for configuration changes and emit events when they occur + if configuration_changed? + emit_event( + OpenFeature::SDK::ProviderEvent::PROVIDER_CONFIGURATION_CHANGED, + message: "Flag configuration updated" + ) + end + end + end +end + +# Remove specific handlers when no longer needed +OpenFeature::SDK.remove_handler(OpenFeature::SDK::ProviderEvent::PROVIDER_READY, ready_handler) +``` ### Shutdown diff --git a/docs/reference/technologies/server/rust.mdx b/docs/reference/sdks/server/rust.mdx similarity index 98% rename from docs/reference/technologies/server/rust.mdx rename to docs/reference/sdks/server/rust.mdx index 78a2e85a1..f890c69df 100644 --- a/docs/reference/technologies/server/rust.mdx +++ b/docs/reference/sdks/server/rust.mdx @@ -9,7 +9,7 @@ This content has been automatically generated from rust-sdk. Edits should be made here: https://github.com/open-feature/rust-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) +Last updated at Fri Jan 23 2026 08:12:21 GMT+0000 (Coordinated Universal Time) -->

@@ -17,7 +17,7 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) Specification - + Release @@ -32,7 +32,7 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) Crates.io - Min rust version + Min rust version Repo status @@ -43,7 +43,7 @@ Last updated at Mon Oct 06 2025 08:10:45 GMT+0000 (Coordinated Universal Time) ### Requirements -This package was built with Rust version `1.70.0`. Earlier versions might work, but is not guaranteed. +This package was built with Rust version `1.77.0`. Earlier versions might work, but is not guaranteed. ### Install diff --git a/docs/tutorials/five-minutes-to-feature-flags.md b/docs/tutorials/five-minutes-to-feature-flags.md index d6f088c31..6a6d8ec97 100644 --- a/docs/tutorials/five-minutes-to-feature-flags.md +++ b/docs/tutorials/five-minutes-to-feature-flags.md @@ -411,7 +411,7 @@ We can get started with feature flags with low investment and low risk, and once ## Next steps To learn more about OpenFeature, check out the documentation [here](/docs/reference/intro). -Specifically, you can read more about how the [evaluation API works](/docs/reference/concepts/evaluation-api/), what [tech stacks are supported](/docs/reference/technologies/), or read [more tutorials](/docs/category/getting-started/) about using OpenFeature in a variety of tech stacks. +Specifically, you can read more about how the [evaluation API works](/docs/reference/concepts/evaluation-api/), what [tech stacks are supported](/docs/reference/sdks/), or read [more tutorials](/docs/category/getting-started/) about using OpenFeature in a variety of tech stacks. More hands-on tutorials are available on the [OpenFeature Killercoda page](https://killercoda.com/open-feature). diff --git a/docs/tutorials/getting-started/dotnet.mdx b/docs/tutorials/getting-started/dotnet.mdx index 0a4545edc..56b916b5f 100644 --- a/docs/tutorials/getting-started/dotnet.mdx +++ b/docs/tutorials/getting-started/dotnet.mdx @@ -45,6 +45,7 @@ With NuGet you can install the latest [OpenFeature](https://www.nuget.org/packag ```shell dotnet add package OpenFeature +dotnet add package OpenFeature.Hosting ``` ### Step 3: Add code @@ -54,7 +55,9 @@ Open a code editor and add the C# code below to the Program.cs. ```csharp // diff-add-block-start +using Microsoft.AspNetCore.Mvc; using OpenFeature; +using OpenFeature.Hosting.Providers.Memory; using OpenFeature.Providers.Memory; // diff-add-block-end @@ -64,13 +67,23 @@ var builder = WebApplication.CreateBuilder(args); // Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi builder.Services.AddOpenApi(); -var app = builder.Build(); - // diff-add-block-start // Register your feature flag provider -await Api.Instance.SetProviderAsync(new InMemoryProvider()); +builder.Services.AddOpenFeature(featureBuilder => +{ + featureBuilder + .AddInMemoryProvider(_ => new Dictionary() + { + { + "welcome-message", new Flag( + new Dictionary { { "show", true }, { "hide", false } }, "show") + } + }); +}); // diff-add-block-end +var app = builder.Build(); + // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { @@ -102,11 +115,9 @@ app.MapGet("/weatherforecast", () => .WithName("GetWeatherForecast"); //diff-remove-block-end //diff-add-block-start -app.MapGet("/hello", async () => +app.MapGet("/hello", async ([FromServices] IFeatureClient featureClient) => { - var client = Api.Instance.GetClient(); - - if (await client.GetBooleanValueAsync("welcome-message", false)) + if (await featureClient.GetBooleanValueAsync("welcome-message", false)) { return "Hello, welcome to this OpenFeature-enabled website!"; } @@ -160,11 +171,15 @@ Finally, let's add the required code change to enable the flagd provider in our ```csharp +using Microsoft.AspNetCore.Mvc; using OpenFeature; -//diff-add -using OpenFeature.Contrib.Providers.Flagd -//diff-remove +//diff-add-block-start +using OpenFeature.DependencyInjection.Providers.Flagd; +//diff-add-block-end +//diff-remove-block-start using OpenFeature.Providers.Memory; +using OpenFeature.Hosting.Providers.Memory; +//diff-remove-block-end var builder = WebApplication.CreateBuilder(args); @@ -175,12 +190,20 @@ builder.Services.AddOpenApi(); var app = builder.Build(); // Register your feature flag provider -//diff-remove -await Api.Instance.SetProviderAsync(new InMemoryProvider()); +builder.Services.AddOpenFeature(featureBuilder => +{ + featureBuilder + .AddInMemoryProvider(_ => new Dictionary() + { + { + "welcome-message", new Flag( + new Dictionary { { "show", true }, { "hide", false } }, "show") + } + }); //diff-add-block-start -var flagdProvider = new FlagdProvider(new Uri("http://localhost:8013")); -await Api.Instance.SetProviderAsync(flagdProvider); + .AddFlagdProvider(); //diff-add-block-end +}); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) @@ -190,11 +213,9 @@ if (app.Environment.IsDevelopment()) app.UseHttpsRedirection(); -app.MapGet("/hello", async () => +app.MapGet("/hello", async ([FromServices] IFeatureClient featureClient) => { - var client = Api.Instance.GetClient(); - - if (await client.GetBooleanValueAsync("welcome-message", false)) + if (await featureClient.GetBooleanValueAsync("welcome-message", false)) { return "Hello, welcome to this OpenFeature-enabled website!"; } diff --git a/docusaurus.config.ts b/docusaurus.config.ts index fc647f6d1..e993d3049 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -8,7 +8,7 @@ import { rehypeGithubAlerts } from 'rehype-github-alerts'; import remarkGfm from 'remark-gfm'; import tailwindcss from 'tailwindcss'; -import { processSdkReadmes } from './scripts/process-sdk-readmes'; +import { processSdkReadmes, processOtherTechnologies } from './scripts/process-sdk-readmes'; const presetClassicOptions: PresetClassicOptions = { docs: { @@ -96,7 +96,7 @@ const themeConfig: ThemeCommonConfig & AlgoliaThemeConfig = { announcementBar: { id: 'announcing-kubecon-na-25', content: - '🎉️ Meet us in Atlanta for KubeCon + CloudNativeCon North America · Nov 10-13 · Register Today! 🥳️', + 'Check out our KubeCon NA \'25 recap, and our new training course!', }, footer: { style: 'dark', @@ -172,7 +172,7 @@ const themeConfig: ThemeCommonConfig & AlgoliaThemeConfig = { }, prism: { theme: themes.oceanicNext, - additionalLanguages: ['java', 'csharp', 'powershell', 'php', 'kotlin', 'ruby', 'dart'], + additionalLanguages: ['java', 'csharp', 'powershell', 'php', 'kotlin', 'ruby', 'dart', 'scala'], magicComments: [ { className: 'theme-code-block-highlighted-line', @@ -206,7 +206,6 @@ const config: Config = { url: 'https://openfeature.dev', baseUrl: '/', onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'warn', i18n: { defaultLocale: 'en', locales: ['en'], @@ -284,7 +283,31 @@ const config: Config = { }, }, ], - presets: [['classic', presetClassicOptions]], + presets: [ + ['classic', presetClassicOptions], + [ + 'redocusaurus', + { + specs: [ + { + id: 'ofrep-api', + spec: 'https://raw.githubusercontent.com/open-feature/protocol/main/service/openapi.yaml', + }, + ], + theme: { + primaryColor: '#1890ff', + options: { + disableSearch: true, + theme: { + sidebar: { + width: '0px', + }, + }, + }, + }, + }, + ], + ], plugins: [ async function tailwind() { return { @@ -319,11 +342,22 @@ const config: Config = { name: 'sdk-content', noRuntimeDownloads: true, sourceBaseUrl: 'https://raw.githubusercontent.com/open-feature/', - outDir: 'docs/reference/technologies', + outDir: 'docs/reference/sdks', documents: processSdkReadmes.paths, modifyContent: processSdkReadmes.modifyContent, }, ], + [ + 'docusaurus-plugin-remote-content', + { + name: 'other-technologies-content', + noRuntimeDownloads: true, + sourceBaseUrl: 'https://raw.githubusercontent.com/open-feature/', + outDir: 'docs/reference/other-technologies', + documents: processOtherTechnologies.paths, + modifyContent: processOtherTechnologies.modifyContent, + }, + ], [ '@docusaurus/plugin-content-docs', { @@ -346,6 +380,9 @@ const config: Config = { if (existingPath.includes('/docs/specification')) { return [existingPath.replace('/docs/specification', '/specification')]; } + if (existingPath.includes('/docs/reference/sdks')) { + return [existingPath.replace('/docs/reference/sdks', '/docs/reference/technologies')]; + } return undefined; // Return a falsy value: no redirect created }, }, @@ -362,8 +399,9 @@ const config: Config = { themeConfig, markdown: { mermaid: true, + hooks: { onBrokenMarkdownLinks: 'warn' }, }, - themes: ['@docusaurus/theme-mermaid'], + themes: ['@docusaurus/theme-mermaid', 'docusaurus-theme-redoc'], }; export default config; diff --git a/external-content/community b/external-content/community index ca0df717c..53bce150a 160000 --- a/external-content/community +++ b/external-content/community @@ -1 +1 @@ -Subproject commit ca0df717c14d92fdc019af7cf6cebccb33d6c6a1 +Subproject commit 53bce150ae0787fc87fc3be7487252440f6da73e diff --git a/external-content/specification b/external-content/specification index 25dac91f8..5c3886866 160000 --- a/external-content/specification +++ b/external-content/specification @@ -1 +1 @@ -Subproject commit 25dac91f8add07cf1a47c43f8ca4a67dae2f41d5 +Subproject commit 5c3886866b4f3a02f6c58f038c00d7a63f2f0ef3 diff --git a/package.json b/package.json index e13c51e5c..0d87174a6 100644 --- a/package.json +++ b/package.json @@ -17,16 +17,16 @@ "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", "typecheck": "tsc", - "update:sdk-docs": "docusaurus download-remote-sdk-content" + "update:sdk-docs": "docusaurus download-remote-sdk-content && docusaurus download-remote-other-technologies-content" }, "engines": { "node": ">20.0.0" }, "dependencies": { - "@docusaurus/core": "^3.9.1", - "@docusaurus/plugin-client-redirects": "^3.9.1", - "@docusaurus/preset-classic": "^3.9.1", - "@docusaurus/theme-mermaid": "^3.9.1", + "@docusaurus/core": "^3.9.2", + "@docusaurus/plugin-client-redirects": "^3.9.2", + "@docusaurus/preset-classic": "^3.9.2", + "@docusaurus/theme-mermaid": "^3.9.2", "@fortawesome/fontawesome-svg-core": "6.7.2", "@fortawesome/free-brands-svg-icons": "6.7.2", "@fortawesome/free-regular-svg-icons": "6.7.2", @@ -57,6 +57,7 @@ "react-instantsearch": "^7.15.8", "react-lite-youtube-embed": "^2.5.1", "react-transition-group": "^4.4.5", + "redocusaurus": "^2.5.0", "rehype-github-alerts": "^4.1.1", "remark-gfm": "^4.0.1", "remarkable": "2.0.1", @@ -68,12 +69,12 @@ "tsconfig-paths": "^4.2.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.9.1", - "@docusaurus/tsconfig": "^3.9.1", + "@docusaurus/module-type-aliases": "^3.9.2", + "@docusaurus/tsconfig": "^3.9.2", "@types/fs-extra": "11.0.4", "@types/react": "^19.1.6", - "@typescript-eslint/parser": "8.35.1", "@typescript-eslint/eslint-plugin": "8.35.1", + "@typescript-eslint/parser": "8.35.1", "eslint": "^8.57.0", "eslint-config-prettier": "10.1.5", "eslint-mdx": "3.6.0", @@ -137,4 +138,4 @@ } }, "packageManager": "yarn@1.22.22+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610" -} +} \ No newline at end of file diff --git a/scripts/process-sdk-readmes.ts b/scripts/process-sdk-readmes.ts index eca63c459..9d172c6d7 100644 --- a/scripts/process-sdk-readmes.ts +++ b/scripts/process-sdk-readmes.ts @@ -8,6 +8,21 @@ const DEFAULT_BRANCH = 'main'; const DEFAULT_FILE_EXTENSION = 'mdx'; const GITHUB_ORG = 'open-feature'; +const SDK_NAME_TO_MCP_MAPPING: Record = { + 'node.js': 'nodejs', + 'nestjs': 'nestjs', + 'go': 'go', + 'python': 'python', + 'java': 'java', + '.net': 'dotnet', + 'php': 'php', + 'ruby': 'ruby', + 'web': 'javascript', + 'react': 'react', + 'kotlin': 'kotlin', + 'ios': 'swift', +}; + /** * Converts carriage return characters to new lines. This is an important preprocessing * step to ensure subsequent regex's match. @@ -97,6 +112,51 @@ Last updated at ${new Date()} ${content}`; }; +/** + * Fix internal doc links from /technologies/ to /sdks/ + */ +const fixInternalDocLinks = (content: string): string => { + return content.replace( + /\/docs\/reference\/technologies\//g, + '/docs/reference/sdks/' + ); +}; + +/** + * Add MCPInstall import statement after frontmatter + */ +const addMCPInstallImport = (mcpTechnology: string | undefined) => (content: string): string => { + if (!mcpTechnology) return content; + + const importStatement = '\nimport MCPInstall from \'@site/src/partials/mcp-install\';\n'; + const frontmatterEnd = content.indexOf('-->'); + + if (frontmatterEnd !== -1) { + const insertPosition = frontmatterEnd + 3; + return content.slice(0, insertPosition) + importStatement + content.slice(insertPosition); + } + + return content; +}; + +/** + * Insert MCPInstall component after "## Quick start" heading + */ +const insertMCPInstallComponent = (mcpTechnology: string | undefined) => (content: string): string => { + if (!mcpTechnology) return content; + + const quickStartPattern = /^#{1,4}\s+quick start$/mi; + const match = content.match(quickStartPattern); + + if (match && match.index !== undefined) { + const insertPosition = match.index + match[0].length; + const component = `\n\n\n`; + return content.slice(0, insertPosition) + component + content.slice(insertPosition); + } + + return content; +}; + const replaceLinks = (repo: { url: string; branch: string; folder?: string }) => { return (content: string) => { const replace = (processRelativeUrl: (url: string) => string) => (url: string) => { @@ -144,6 +204,8 @@ const markdownProcessor = (sdks: SDK[]) => { const fileExtension = sdk.fileExtension ?? DEFAULT_FILE_EXTENSION; const branch = sdk.branch ?? DEFAULT_BRANCH; + const mcpTechnology = sdk.name ? SDK_NAME_TO_MCP_MAPPING[sdk.name.toLowerCase()] : undefined; + const content = [ carriageReturnsToNewLines, removeEmojisFromHeaders, @@ -153,7 +215,10 @@ const markdownProcessor = (sdks: SDK[]) => { removeExtraNewlinesBetweenSections, removeExtraNewlinesAtTop, addHeader({ name: sdk.name, repo: sdk.repo, url: repoUrl, fileName, slug: sdk.slug, id: sdk.id }), + addMCPInstallImport(mcpTechnology), replaceLinks({ url: repoUrl, branch, folder: sdk.folder }), + fixInternalDocLinks, + insertMCPInstallComponent(mcpTechnology), ].reduce((currentContent, processor) => processor(currentContent), initialContent); if (sdk.includeInSupportMatrix ?? true) { @@ -193,3 +258,93 @@ export const processSdkReadmes = { }), modifyContent: markdownProcessor(SDKS), }; + +/** + * Other Technologies content configuration + */ +type OtherTechnology = { + repo: string; + id: string; + title: string; + label: string; + position: number; + branch: string; + filename?: string; +}; + +const OTHER_TECHNOLOGIES: OtherTechnology[] = [ + { repo: 'cli', id: 'cli', title: 'OpenFeature CLI', label: 'CLI', position: 1, branch: 'main' }, + { repo: 'protocol', id: 'ofrep', title: 'OpenFeature Remote Evaluation Protocol (OFREP)', label: 'OFREP', position: 2, branch: 'main', filename: 'ofrep/index.mdx' }, + { repo: 'mcp', id: 'mcp', title: 'OpenFeature MCP Server', label: 'MCP', position: 3, branch: 'main' }, +]; + +/** + * Transforms Other Technologies READMEs for inclusion in the OpenFeature docs. + */ +export const processOtherTechnologies = { + paths: OTHER_TECHNOLOGIES.map((tech) => `${tech.repo}/${tech.branch}/README.md`), + modifyContent: (file: string, initialContent: string): { filename: string; content: string } => { + const tech = OTHER_TECHNOLOGIES.find((t) => file.startsWith(`${t.repo}/`)); + + if (!tech) { + throw new Error(`Unable to modify content for ${file}`); + } + + const frontmatter = `--- +title: ${tech.title} +sidebar_label: ${tech.label} +sidebar_position: ${tech.position} +id: ${tech.id} +--- + +`; + + // Convert relative links to absolute GitHub URLs + const fixRelativeLinks = (content: string): string => { + const repoUrl = `https://github.com/${GITHUB_ORG}/${tech.repo}`; + const branch = tech.branch || 'main'; + + // Convert relative markdown links to GitHub URLs + return content.replace( + /\[([^\]]+)\]\(\.\/([^)]+)\)/g, + (match, text, path) => { + // Skip if it's already an absolute URL + if (path.startsWith('http')) return match; + return `[${text}](${repoUrl}/blob/${branch}/${path})`; + } + ); + }; + + // Replace service/openapi.yaml links with docs link for OFREP OpenAPI viewer + const replaceOFREPOpenApiLinks = (content: string): string => { + if (tech.id !== 'ofrep') return content; + + // Replace links to service/openapi.yaml with docs link + return content.replace( + /\[([^\]]+)\]\([^)]*service\/openapi\.yaml[^)]*\)/g, + (match, text) => { + return `[${text}](/docs/reference/other-technologies/ofrep/openapi)`; + } + ); + }; + + const processors = [ + carriageReturnsToNewLines, + removeEmojisFromHeaders, + removeSections, + removeLine, + removeComments, + removeExtraNewlinesBetweenSections, + removeExtraNewlinesAtTop, + fixRelativeLinks, + replaceOFREPOpenApiLinks, + ]; + + const content = processors.reduce((currentContent, processor) => processor(currentContent), initialContent); + + return { + filename: tech.filename || `${tech.id}.mdx`, + content: frontmatter + content, + }; + }, +}; diff --git a/src/components/custom/CourseCard/index.tsx b/src/components/custom/CourseCard/index.tsx new file mode 100644 index 000000000..b603e1cb3 --- /dev/null +++ b/src/components/custom/CourseCard/index.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import Link from '@docusaurus/Link'; + +type CourseCardProps = { + href: string; + imageUrl: string; + imageAlt: string; + title: string; + subtitle: string; + description: string | string[]; +}; + +export const CourseCard: React.FC = ({ href, imageUrl, imageAlt, title, subtitle, description }) => { + const paragraphs = Array.isArray(description) ? description : [description]; + + return ( + +

+ {imageAlt} +
+

{title}

+

{subtitle}

+
+ {paragraphs.map((paragraph, index) => ( +

+ {paragraph} +

+ ))} +
+
+
+ + ); +}; diff --git a/src/components/custom/index.ts b/src/components/custom/index.ts index 3c2d6e883..c9270ea95 100644 --- a/src/components/custom/index.ts +++ b/src/components/custom/index.ts @@ -1,4 +1,5 @@ export * from './OpenFeatureComponentCard'; export * from './OpenFeatureComponentTable'; export * from './OpenFeatureTechnologiesPage'; -export * from './CopyChecklist'; \ No newline at end of file +export * from './CopyChecklist'; +export * from './CourseCard'; \ No newline at end of file diff --git a/src/css/custom.css b/src/css/custom.css index db8b0fc2e..de4355d31 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -15,6 +15,7 @@ --github-alert-default-color: rgb(175, 184, 193); --github-alert-warning-color: rgb(154, 103, 0); --github-alert-note-color: rgb(9, 105, 218); + --docsearch-muted-color: #525860; } .footer { @@ -24,7 +25,8 @@ /* For readability concerns, you should choose a lighter palette in dark mode. */ [data-theme='dark'] { --ifm-color-primary: #8D8DFF; - --ifm-navbar-background-color: #33363A; + --ifm-navbar-background-color: #33363A; + --docsearch-muted-color: var(--ifm-color-secondary-darkest); } .header-github-link:hover { @@ -36,13 +38,11 @@ width: 24px; height: 24px; display: flex; - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") - no-repeat; + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat; } [data-theme='dark'] .header-github-link::before { - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") - no-repeat; + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat; } .prism-code { @@ -69,7 +69,8 @@ .card-container *:last-child { margin-bottom: 0; } -.code-block-diff-remove-line{ + +.code-block-diff-remove-line { background-color: #ff00001f; display: block; margin: 0 calc(-1 * var(--ifm-pre-padding)); @@ -77,7 +78,7 @@ border-left: 3px solid #ff000080; } -.code-block-diff-add-line{ +.code-block-diff-add-line { background-color: #00ff001f; display: block; margin: 0 calc(-1 * var(--ifm-pre-padding)); @@ -89,11 +90,13 @@ .github-badges { text-align: start; } + /* Add some space between github badges */ .github-badges>a { margin-left: 2px; margin-right: 2px; } + /* center the footer items' content */ .footer__item { text-align: center; @@ -113,6 +116,7 @@ background-color: white !important; border-radius: var(--ifm-global-radius); } + /** * Disables the copy button on a code block if the language is * set to 'disable-copy-button'. @@ -131,6 +135,7 @@ margin: 0; line-height: normal; } + .has-tooltip:hover .tooltip { @apply visible z-50; } @@ -150,6 +155,7 @@ margin-bottom: 16px; border-left: 0.25em solid var(--github-alert-default-color); } + .markdown-alert-note .markdown-alert-title, .markdown-alert-note .markdown-alert-title>svg { color: var(--github-alert-note-color); @@ -159,6 +165,7 @@ .markdown-alert-note { border-left-color: var(--github-alert-note-color); } + .markdown-alert-important .markdown-alert-title, .markdown-alert-important .markdown-alert-title>svg { color: var(--github-alert-important-color); @@ -168,6 +175,7 @@ .markdown-alert-important { border-left-color: var(--github-alert-important-color); } + .markdown-alert-warning .markdown-alert-title, .markdown-alert-warning .markdown-alert-title>svg { color: var(--github-alert-warning-color); @@ -202,19 +210,22 @@ width: 100%; transition: all 0.2s cubic-bezier(0, 0, 0.2, 1); } + .yt-lite::after { content: ""; display: block; padding-bottom: var(--aspect-ratio); } -.yt-lite > iframe { + +.yt-lite>iframe { width: 100%; height: 100%; position: absolute; top: 0; left: 0; } -.yt-lite > .lty-playbtn { + +.yt-lite>.lty-playbtn { width: 70px; height: 46px; background-color: #212121; @@ -223,28 +234,33 @@ border-radius: 14%; transition: all 0.2s cubic-bezier(0, 0, 0.2, 1); } -.yt-lite:hover > .lty-playbtn { + +.yt-lite:hover>.lty-playbtn { background-color: red; opacity: 1; } -.yt-lite > .lty-playbtn::before { + +.yt-lite>.lty-playbtn::before { content: ""; border-color: transparent transparent transparent #fff; border-style: solid; border-width: 11px 0 11px 19px; } -.yt-lite > .lty-playbtn, -.yt-lite > .lty-playbtn::before { + +.yt-lite>.lty-playbtn, +.yt-lite>.lty-playbtn::before { position: absolute; top: 50%; left: 50%; transform: translate3d(-50%, -50%, 0); } + .yt-lite.lyt-activated { cursor: unset; } + .yt-lite.lyt-activated::before, -.yt-lite.lyt-activated > .lty-playbtn { +.yt-lite.lyt-activated>.lty-playbtn { opacity: 0; pointer-events: none; } @@ -258,7 +274,106 @@ margin: 0 auto; } -.yt-lite > .lty-playbtn { +.yt-lite>.lty-playbtn { cursor: pointer; border: 0; -} \ No newline at end of file +} + +.mcp-install-summary { + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + list-style: none; +} + +.mcp-install-summary::-webkit-details-marker { + display: none; +} + +.mcp-install-summary strong::before { + content: '▶'; + display: inline-block; + width: 1em; + text-align: center; + margin-right: 0.5em; +} + +details[open] .mcp-install-summary strong::before { + content: '▼'; +} + +.mcp-install-button { + display: inline-flex; + align-items: center; + padding: 8px 16px; + background-color: var(--ifm-color-primary); + color: #fff; + border: 1px solid var(--ifm-color-primary); + border-radius: 6px; + font-size: 14px; + font-weight: 500; + text-decoration: none; + cursor: pointer; + transition: all 0.15s ease-in-out; + margin-bottom: 10px; +} + +.mcp-install-button:hover { + background-color: var(--ifm-color-primary-dark); + border-color: var(--ifm-color-primary-dark); + color: #fff; + text-decoration: none; +} + +[data-theme='dark'] .mcp-install-button { + background-color: var(--ifm-color-primary); + border-color: var(--ifm-color-primary); + color: #fff; +} + +[data-theme='dark'] .mcp-install-button:hover { + background-color: var(--ifm-color-primary-light); + border-color: var(--ifm-color-primary-light); + color: #fff; + text-decoration: none; +} + +/* Full width Redoc API viewer */ +.redoc-container { + margin: -2rem calc(-1 * var(--ifm-spacing-horizontal)); + max-width: none; +} + +/* Expand parent containers for full width */ +article:has(.redoc-container) { + max-width: none !important; +} + +/* Force doc column to full width when Redoc is present */ +.main-wrapper:has(.redoc-container) [class*="docItemCol"] { + max-width: none !important; + flex-basis: 100% !important; +} + +/* Hide Redocly branding */ +.redocusaurus a[href*="redocly.com"], +.redocusaurus [class*="powered-by"] { + display: none !important; +} + +/* Hide menu border on API viewer pages */ +.redoc-container .menu-content { + border-right: none !important; +} + +/* + * Fixes an issue where the focus ring from @tailwindcss/forms + * overlaps with the Algolia DocSearch component's internal UI. + */ +.DocSearch-Input:focus { + --tw-ring-offset-shadow: none; + --tw-ring-shadow: none; + box-shadow: none; +} + diff --git a/src/datasets/constants.ts b/src/datasets/constants.ts index 09cc33675..742f353a5 100644 --- a/src/datasets/constants.ts +++ b/src/datasets/constants.ts @@ -18,6 +18,7 @@ export const serverSideFeatures = [ 'Transaction Context Propagation', 'Shutdown', 'Extending', + 'Multi-Provider', ]; export const clientSideFeatures = [ @@ -31,4 +32,5 @@ export const clientSideFeatures = [ 'Tracking', 'Shutdown', 'Extending', + 'Multi-Provider', ]; diff --git a/src/datasets/hooks/debounce.ts b/src/datasets/hooks/debounce.ts new file mode 100644 index 000000000..161f7fe1c --- /dev/null +++ b/src/datasets/hooks/debounce.ts @@ -0,0 +1,16 @@ +import StopWatch from '@site/static/img/stopwatch-no-fill.svg'; +import { Hook } from '.'; + +export const Debounce: Hook = { + name: 'Debounce', + logo: StopWatch, + description: 'Rate-limits or "debounces" hook executions', + technologies: [ + { + technology: 'JavaScript', + vendorOfficial: false, + href: 'https://github.com/open-feature/js-sdk-contrib/tree/main/libs/hooks/debounce', + category: ['Server', 'Client'], + }, + ], +}; diff --git a/src/datasets/hooks/index.ts b/src/datasets/hooks/index.ts index 44c2e2779..08be349c6 100644 --- a/src/datasets/hooks/index.ts +++ b/src/datasets/hooks/index.ts @@ -1,11 +1,12 @@ import type { ComponentType, SVGProps } from 'react'; import { OpenTelemetry } from './opentelemetry'; import { Validation } from './validation'; +import { Debounce } from './debounce'; import { Datadog } from './datadog'; import { Sentry } from './sentry'; import { Category, EcosystemElement, Technology } from '../types'; -export const ECOSYSTEM_HOOKS: EcosystemElement[] = [OpenTelemetry, Validation, Datadog, Sentry] +export const ECOSYSTEM_HOOKS: EcosystemElement[] = [OpenTelemetry, Validation, Datadog, Sentry, Debounce] .map((hook) => { return hook.technologies.map(({ vendorOfficial, technology, href, category }): EcosystemElement => { return { diff --git a/src/datasets/providers/awsssm.ts b/src/datasets/providers/awsssm.ts index cde78684e..9ac64921f 100644 --- a/src/datasets/providers/awsssm.ts +++ b/src/datasets/providers/awsssm.ts @@ -11,5 +11,11 @@ export const AwsSSM: Provider = { href: 'https://github.com/open-feature/js-sdk-contrib/tree/main/libs/providers/aws-ssm', category: ['Server'], }, + { + technology: 'Go', + vendorOfficial: false, + href: 'https://github.com/open-feature/go-sdk-contrib/tree/main/providers/aws-ssm', + category: ['Server'], + }, ], }; diff --git a/src/datasets/providers/bucketeer.ts b/src/datasets/providers/bucketeer.ts index 64b2a3e82..f02ab5653 100644 --- a/src/datasets/providers/bucketeer.ts +++ b/src/datasets/providers/bucketeer.ts @@ -24,6 +24,12 @@ export const Bucketeer: Provider = { href: 'https://www.npmjs.com/package/@bucketeer/openfeature-js-client-sdk', category: ['Client'], }, + { + technology: 'JavaScript', + vendorOfficial: true, + href: 'https://www.npmjs.com/package/@bucketeer/openfeature-node-server-sdk', + category: ['Server'], + }, { technology: 'Go', vendorOfficial: true, diff --git a/src/datasets/providers/datadog.ts b/src/datasets/providers/datadog.ts new file mode 100644 index 000000000..44351cc2f --- /dev/null +++ b/src/datasets/providers/datadog.ts @@ -0,0 +1,21 @@ +import DatadogSvg from '@site/static/img/datadog-no-fill.svg'; +import { Provider } from '.'; + +export const Datadog: Provider = { + name: 'Datadog', + logo: DatadogSvg, + technologies: [ + { + technology: 'JavaScript', + vendorOfficial: true, + href: 'https://www.npmjs.com/package/@datadog/openfeature-node-server', + category: ['Server'], + }, + { + technology: 'JavaScript', + vendorOfficial: true, + href: 'https://www.npmjs.com/package/@datadog/openfeature-browser', + category: ['Client'], + }, + ], +}; diff --git a/src/datasets/providers/flagsmith.ts b/src/datasets/providers/flagsmith.ts index e7621446d..5cca2bcf9 100644 --- a/src/datasets/providers/flagsmith.ts +++ b/src/datasets/providers/flagsmith.ts @@ -41,5 +41,17 @@ export const Flagsmith: Provider = { href: 'https://github.com/Flagsmith/flagsmith-openfeature-provider-python', category: ['Server'], }, + { + technology: 'Ruby', + vendorOfficial: true, + href: 'https://github.com/open-feature/ruby-sdk-contrib/tree/main/providers/openfeature-flagsmith-provider', + category: ['Server'], + }, + { + technology: 'Rust', + vendorOfficial: true, + href: 'https://github.com/open-feature/rust-sdk-contrib/tree/main/crates/flagsmith', + category: ['Server'], + }, ], }; diff --git a/src/datasets/providers/hyphen.ts b/src/datasets/providers/hyphen.ts new file mode 100644 index 000000000..44d8d7f9b --- /dev/null +++ b/src/datasets/providers/hyphen.ts @@ -0,0 +1,51 @@ +import HyphenNoFillSvg from '@site/static/img/hyphen-no-fill.svg'; +import { Provider } from '.'; + +export const Hyphen: Provider = { + name: 'Hyphen AI', + logo: HyphenNoFillSvg, + technologies: [ + { + technology: '.NET', + vendorOfficial: true, + href: 'https://github.com/Hyphen/openfeature-provider-dotnet', + category: ['Server'], + }, + { + technology: 'Go', + vendorOfficial: false, + href: 'https://github.com/Hyphen/openfeature-provider-go', + category: ['Server'], + }, + { + technology: 'Java', + vendorOfficial: true, + href: 'https://github.com/Hyphen/openfeature-provider-java', + category: ['Server'], + }, + { + technology: 'JavaScript', + vendorOfficial: true, + href: 'https://github.com/Hyphen/openfeature-provider-javascript-web', + category: ['Client'], + }, + { + technology: 'JavaScript', + vendorOfficial: true, + href: 'https://github.com/Hyphen/openfeature-provider-javascript-server', + category: ['Server'], + }, + { + technology: 'Python', + vendorOfficial: true, + href: 'https://github.com/Hyphen/openfeature-provider-python', + category: ['Server'], + }, + { + technology: 'Swift', + vendorOfficial: true, + href: 'https://github.com/Hyphen/hyphen-openfeature-swift', + category: ['Client'], + }, + ], +}; diff --git a/src/datasets/providers/index.ts b/src/datasets/providers/index.ts index 14c53bf63..899da49da 100644 --- a/src/datasets/providers/index.ts +++ b/src/datasets/providers/index.ts @@ -5,6 +5,7 @@ import { AwsSSM } from './awsssm'; import { Bucketeer } from './bucketeer'; import { CloudBees } from './cloudbees'; import { ConfigCat } from './configcat'; +import { Datadog } from './datadog'; import { DevCycle } from './devcycle'; import { EnvVar } from './env-var'; import { Flagd } from './flagd'; @@ -12,10 +13,12 @@ import { Flagsmith } from './flagsmith'; import { Flipt } from './flipt'; import { Goff } from './goff'; import { Harness } from './harness'; +import { Hyphen } from './hyphen'; import { Kameleoon } from './kameleoon'; import { LaunchDarkly } from './launchdarkly'; import { MDBRules } from './mdb-rules'; import { PostHog } from './posthog'; +import { Prefab } from './prefab'; import { Reflag } from './reflag'; import { Split } from './split'; import { Unleash } from './unleash'; @@ -55,6 +58,7 @@ export const PROVIDERS: Provider[] = [ Confidence, ConfigBee, ConfigCat, + Datadog, DevCycle, EnvVar, FeatBit, @@ -63,11 +67,13 @@ export const PROVIDERS: Provider[] = [ Flipt, Goff, Harness, + Hyphen, Hypertune, Kameleoon, LaunchDarkly, MDBRules, PostHog, + Prefab, Reflag, Split, Statsig, diff --git a/src/datasets/providers/multi-provider.ts b/src/datasets/providers/multi-provider.ts index 7047d1726..fe2c05815 100644 --- a/src/datasets/providers/multi-provider.ts +++ b/src/datasets/providers/multi-provider.ts @@ -9,13 +9,13 @@ export const MultiProvider: Provider = { { technology: 'JavaScript', vendorOfficial: false, - href: 'https://github.com/open-feature/js-sdk-contrib/tree/main/libs/providers/multi-provider', + href: 'https://github.com/open-feature/js-sdk/tree/main/packages/server#multi-provider', category: ['Server'], }, { technology: 'JavaScript', vendorOfficial: false, - href: 'https://github.com/open-feature/js-sdk-contrib/tree/main/libs/providers/multi-provider-web', + href: 'https://github.com/open-feature/js-sdk/tree/main/packages/web#multi-provider', category: ['Client'], }, { @@ -24,5 +24,11 @@ export const MultiProvider: Provider = { href: 'https://github.com/open-feature/java-sdk-contrib/tree/main/providers/multiprovider', category: ['Server'], }, + { + technology: '.NET', + vendorOfficial: false, + href: 'https://github.com/open-feature/dotnet-sdk/tree/main/src/OpenFeature.Providers.MultiProvider', + category: ['Server'], + } ], }; diff --git a/src/datasets/providers/ofrep.ts b/src/datasets/providers/ofrep.ts index 2f23454c4..1da04ebd7 100644 --- a/src/datasets/providers/ofrep.ts +++ b/src/datasets/providers/ofrep.ts @@ -36,5 +36,11 @@ export const OFREP: Provider = { href: 'https://github.com/open-feature/dotnet-sdk-contrib/tree/main/src/OpenFeature.Providers.Ofrep', vendorOfficial: true, }, + { + technology: 'Java', + category: ['Server'], + href: 'https://github.com/open-feature/java-sdk-contrib/tree/main/providers/ofrep', + vendorOfficial: true, + }, ], }; diff --git a/src/datasets/providers/prefab.ts b/src/datasets/providers/prefab.ts new file mode 100644 index 000000000..c26700f81 --- /dev/null +++ b/src/datasets/providers/prefab.ts @@ -0,0 +1,16 @@ +import PrefabSvg from '@site/static/img/prefab-no-fill.svg'; +import { Provider } from '.'; + +export const Prefab: Provider = { + name: 'Prefab', + logo: PrefabSvg, + technologies: [ + { + technology: 'Go', + vendorOfficial: false, + href: 'https://github.com/open-feature/go-sdk-contrib/tree/main/providers/prefab', + category: ['Server'], + }, + ], +}; + diff --git a/src/datasets/providers/split.ts b/src/datasets/providers/split.ts index 468579997..d427e8c81 100644 --- a/src/datasets/providers/split.ts +++ b/src/datasets/providers/split.ts @@ -11,6 +11,12 @@ export const Split: Provider = { href: 'https://github.com/splitio/split-openfeature-provider-js', category: ['Server'], }, + { + technology: 'JavaScript', + vendorOfficial: true, + href: 'https://github.com/splitio/split-openfeature-provider-web-js', + category: ['Client'], + }, { technology: 'Go', vendorOfficial: true, @@ -35,5 +41,17 @@ export const Split: Provider = { href: 'https://github.com/open-feature/php-sdk-contrib/tree/main/providers/Split', category: ['Server'], }, + { + technology: 'Swift', + vendorOfficial: true, + href: 'https://github.com/splitio/split-openfeature-provider-swift', + category: ['Client'], + }, + { + technology: 'Kotlin', + vendorOfficial: true, + href: 'https://github.com/splitio/split-openfeature-provider-android', + category: ['Client'], + }, ], }; diff --git a/src/datasets/providers/vwo.ts b/src/datasets/providers/vwo.ts index 760e0d7ff..c33be1de8 100644 --- a/src/datasets/providers/vwo.ts +++ b/src/datasets/providers/vwo.ts @@ -25,7 +25,7 @@ export const VWO: Provider = { }, { technology: 'PHP', - vendorOfficial: false, + vendorOfficial: true, href: 'https://github.com/wingify/vwo-openfeature-provider-php', category: ['Server'], }, @@ -35,5 +35,11 @@ export const VWO: Provider = { href: 'https://github.com/wingify/vwo-openfeature-provider-python', category: ['Server'], }, + { + technology: 'Go', + vendorOfficial: true, + href: 'https://github.com/wingify/vwo-openfeature-provider-go', + category: ['Server'], + } ], }; diff --git a/src/datasets/sdks/angular.ts b/src/datasets/sdks/angular.ts index efec1112d..50567f1dd 100644 --- a/src/datasets/sdks/angular.ts +++ b/src/datasets/sdks/angular.ts @@ -11,6 +11,6 @@ export const Angular: SDK = { logoKey: 'angular-no-fill.svg', technology: 'Angular', parentTechnology: 'JavaScript', - href: '/docs/reference/technologies/client/web/angular', + href: '/docs/reference/sdks/client/web/angular', includeInSupportMatrix: false, }; diff --git a/src/datasets/sdks/dart.ts b/src/datasets/sdks/dart.ts index d6103291f..8f79a54ae 100644 --- a/src/datasets/sdks/dart.ts +++ b/src/datasets/sdks/dart.ts @@ -6,5 +6,5 @@ export const Dart: SDK = { repo: 'dart-server-sdk', logoKey: 'dart-no-fill.svg', technology: 'Dart', - href: '/docs/reference/technologies/server/dart', + href: '/docs/reference/sdks/server/dart', }; diff --git a/src/datasets/sdks/dotnet.ts b/src/datasets/sdks/dotnet.ts index de61e5ede..6ddb86ece 100644 --- a/src/datasets/sdks/dotnet.ts +++ b/src/datasets/sdks/dotnet.ts @@ -9,5 +9,5 @@ export const Dotnet: SDK = { branch: 'main', logoKey: 'c-sharp-no-fill.svg', technology: '.NET', - href: '/docs/reference/technologies/server/dotnet', + href: '/docs/reference/sdks/server/dotnet', }; diff --git a/src/datasets/sdks/go.ts b/src/datasets/sdks/go.ts index 8314f2169..f093a4fb0 100644 --- a/src/datasets/sdks/go.ts +++ b/src/datasets/sdks/go.ts @@ -6,5 +6,5 @@ export const Go: SDK = { repo: 'go-sdk', logoKey: 'go-no-fill.svg', technology: 'Go', - href: '/docs/reference/technologies/server/go', + href: '/docs/reference/sdks/server/go', }; diff --git a/src/datasets/sdks/java.ts b/src/datasets/sdks/java.ts index 9d54b04b3..71790fa20 100644 --- a/src/datasets/sdks/java.ts +++ b/src/datasets/sdks/java.ts @@ -6,5 +6,5 @@ export const Java: SDK = { repo: 'java-sdk', logoKey: 'java-no-fill.svg', technology: 'Java', - href: '/docs/reference/technologies/server/java', + href: '/docs/reference/sdks/server/java', }; diff --git a/src/datasets/sdks/kotlin.ts b/src/datasets/sdks/kotlin.ts index 6875f7d28..904e48b1c 100644 --- a/src/datasets/sdks/kotlin.ts +++ b/src/datasets/sdks/kotlin.ts @@ -9,5 +9,5 @@ export const Kotlin: SDK = { repo: 'kotlin-sdk', logoKey: 'kotlin-no-fill.svg', technology: 'Kotlin', - href: '/docs/reference/technologies/client/kotlin', + href: '/docs/reference/sdks/client/kotlin', }; diff --git a/src/datasets/sdks/nestjs.ts b/src/datasets/sdks/nestjs.ts index 1655f050f..d213094da 100644 --- a/src/datasets/sdks/nestjs.ts +++ b/src/datasets/sdks/nestjs.ts @@ -11,6 +11,6 @@ export const Nestjs: SDK = { logoKey: 'nestjs-no-fill.svg', technology: 'NestJS', parentTechnology: 'JavaScript', - href: '/docs/reference/technologies/server/javascript/nestjs', + href: '/docs/reference/sdks/server/javascript/nestjs', includeInSupportMatrix: false, }; diff --git a/src/datasets/sdks/nodejs.ts b/src/datasets/sdks/nodejs.ts index 7454b8d88..038e03240 100644 --- a/src/datasets/sdks/nodejs.ts +++ b/src/datasets/sdks/nodejs.ts @@ -9,5 +9,5 @@ export const Nodejs: SDK = { folder: '/packages/server', logoKey: 'nodejs-no-fill.svg', technology: 'JavaScript', - href: '/docs/reference/technologies/server/javascript', + href: '/docs/reference/sdks/server/javascript', }; diff --git a/src/datasets/sdks/php.ts b/src/datasets/sdks/php.ts index 8135bda12..ce20b0636 100644 --- a/src/datasets/sdks/php.ts +++ b/src/datasets/sdks/php.ts @@ -6,5 +6,5 @@ export const PHP: SDK = { repo: 'php-sdk', logoKey: 'php-no-fill.svg', technology: 'PHP', - href: '/docs/reference/technologies/server/php', + href: '/docs/reference/sdks/server/php', }; diff --git a/src/datasets/sdks/python.ts b/src/datasets/sdks/python.ts index 0e38b2db6..9060d1c65 100644 --- a/src/datasets/sdks/python.ts +++ b/src/datasets/sdks/python.ts @@ -6,5 +6,5 @@ export const Python: SDK = { repo: 'python-sdk', logoKey: 'python-no-fill.svg', technology: 'Python', - href: '/docs/reference/technologies/server/python', + href: '/docs/reference/sdks/server/python', }; diff --git a/src/datasets/sdks/react.ts b/src/datasets/sdks/react.ts index eecb22108..9fa5aeff3 100644 --- a/src/datasets/sdks/react.ts +++ b/src/datasets/sdks/react.ts @@ -11,6 +11,6 @@ export const React: SDK = { logoKey: 'react-no-fill.svg', technology: 'React', parentTechnology: 'JavaScript', - href: '/docs/reference/technologies/client/web/react', + href: '/docs/reference/sdks/client/web/react', includeInSupportMatrix: false, }; diff --git a/src/datasets/sdks/ruby.ts b/src/datasets/sdks/ruby.ts index 0db2219d6..a3de98fc6 100644 --- a/src/datasets/sdks/ruby.ts +++ b/src/datasets/sdks/ruby.ts @@ -9,5 +9,5 @@ export const Ruby: SDK = { branch: 'main', logoKey: 'ruby-no-fill.svg', technology: 'Ruby', - href: '/docs/reference/technologies/server/ruby', + href: '/docs/reference/sdks/server/ruby', }; diff --git a/src/datasets/sdks/rust.ts b/src/datasets/sdks/rust.ts index f78b11c7a..08ad719dd 100644 --- a/src/datasets/sdks/rust.ts +++ b/src/datasets/sdks/rust.ts @@ -6,5 +6,5 @@ export const Rust: SDK = { repo: 'rust-sdk', logoKey: 'rust-no-fill.svg', technology: 'Rust', - href: '/docs/reference/technologies/server/rust', + href: '/docs/reference/sdks/server/rust', }; diff --git a/src/datasets/sdks/sdk-compatibility.json b/src/datasets/sdks/sdk-compatibility.json index 024011438..a0da84624 100644 --- a/src/datasets/sdks/sdk-compatibility.json +++ b/src/datasets/sdks/sdk-compatibility.json @@ -1,11 +1,11 @@ [ { "name": "Java", - "path": "/docs/reference/technologies/server/java", + "path": "/docs/reference/sdks/server/java", "category": "Server", "release": { - "href": "https://github.com/open-feature/java-sdk/releases/tag/v1.18.1", - "version": "1.18.1", + "href": "https://github.com/open-feature/java-sdk/releases/tag/v1.20.1", + "version": "1.20.1", "stable": true }, "spec": { @@ -15,53 +15,57 @@ "features": { "Providers": { "status": "✅", - "path": "/docs/reference/technologies/server/java#providers" + "path": "/docs/reference/sdks/server/java#providers" }, "Targeting": { "status": "✅", - "path": "/docs/reference/technologies/server/java#targeting" + "path": "/docs/reference/sdks/server/java#targeting" }, "Hooks": { "status": "✅", - "path": "/docs/reference/technologies/server/java#hooks" + "path": "/docs/reference/sdks/server/java#hooks" }, "Logging": { "status": "✅", - "path": "/docs/reference/technologies/server/java#logging" + "path": "/docs/reference/sdks/server/java#logging" }, "Domains": { "status": "✅", - "path": "/docs/reference/technologies/server/java#domains" + "path": "/docs/reference/sdks/server/java#domains" }, "Eventing": { "status": "✅", - "path": "/docs/reference/technologies/server/java#eventing" + "path": "/docs/reference/sdks/server/java#eventing" }, "Tracking": { "status": "✅", - "path": "/docs/reference/technologies/server/java#tracking" + "path": "/docs/reference/sdks/server/java#tracking" }, "Transaction Context Propagation": { "status": "✅", - "path": "/docs/reference/technologies/server/java#transaction-context-propagation" + "path": "/docs/reference/sdks/server/java#transaction-context-propagation" }, "Shutdown": { "status": "✅", - "path": "/docs/reference/technologies/server/java#shutdown" + "path": "/docs/reference/sdks/server/java#shutdown" }, "Extending": { "status": "✅", - "path": "/docs/reference/technologies/server/java#extending" + "path": "/docs/reference/sdks/server/java#extending" + }, + "Multi-Provider": { + "status": "❓", + "path": "/docs/reference/sdks/server/java" } } }, { "name": "Node.js", - "path": "/docs/reference/technologies/server/javascript", + "path": "/docs/reference/sdks/server/javascript", "category": "Server", "release": { - "href": "https://github.com/open-feature/js-sdk/releases/tag/server-sdk-v1.19.0", - "version": "1.19.0", + "href": "https://github.com/open-feature/js-sdk/releases/tag/server-sdk-v1.20.1", + "version": "1.20.1", "stable": true }, "spec": { @@ -71,53 +75,57 @@ "features": { "Providers": { "status": "✅", - "path": "/docs/reference/technologies/server/javascript#providers" + "path": "/docs/reference/sdks/server/javascript#providers" }, "Targeting": { "status": "✅", - "path": "/docs/reference/technologies/server/javascript#targeting" + "path": "/docs/reference/sdks/server/javascript#targeting" }, "Hooks": { "status": "✅", - "path": "/docs/reference/technologies/server/javascript#hooks" + "path": "/docs/reference/sdks/server/javascript#hooks" }, "Logging": { "status": "✅", - "path": "/docs/reference/technologies/server/javascript#logging" + "path": "/docs/reference/sdks/server/javascript#logging" }, "Domains": { "status": "✅", - "path": "/docs/reference/technologies/server/javascript#domains" + "path": "/docs/reference/sdks/server/javascript#domains" }, "Eventing": { "status": "✅", - "path": "/docs/reference/technologies/server/javascript#eventing" + "path": "/docs/reference/sdks/server/javascript#eventing" }, "Tracking": { "status": "✅", - "path": "/docs/reference/technologies/server/javascript#tracking" + "path": "/docs/reference/sdks/server/javascript#tracking" }, "Transaction Context Propagation": { "status": "✅", - "path": "/docs/reference/technologies/server/javascript#transaction-context-propagation" + "path": "/docs/reference/sdks/server/javascript#transaction-context-propagation" }, "Shutdown": { "status": "✅", - "path": "/docs/reference/technologies/server/javascript#shutdown" + "path": "/docs/reference/sdks/server/javascript#shutdown" }, "Extending": { "status": "✅", - "path": "/docs/reference/technologies/server/javascript#extending" + "path": "/docs/reference/sdks/server/javascript#extending" + }, + "Multi-Provider": { + "status": "✅", + "path": "/docs/reference/sdks/server/javascript#multi-provider" } } }, { "name": ".NET", - "path": "/docs/reference/technologies/server/dotnet", + "path": "/docs/reference/sdks/server/dotnet", "category": "Server", "release": { - "href": "https://github.com/open-feature/dotnet-sdk/releases/tag/v2.8.1", - "version": "2.8.1", + "href": "https://github.com/open-feature/dotnet-sdk/releases/tag/v2.11.1", + "version": "2.11.1", "stable": true }, "spec": { @@ -127,53 +135,57 @@ "features": { "Providers": { "status": "✅", - "path": "/docs/reference/technologies/server/dotnet#providers" + "path": "/docs/reference/sdks/server/dotnet#providers" }, "Targeting": { "status": "✅", - "path": "/docs/reference/technologies/server/dotnet#targeting" + "path": "/docs/reference/sdks/server/dotnet#targeting" }, "Hooks": { "status": "✅", - "path": "/docs/reference/technologies/server/dotnet#hooks" + "path": "/docs/reference/sdks/server/dotnet#hooks" }, "Logging": { "status": "✅", - "path": "/docs/reference/technologies/server/dotnet#logging" + "path": "/docs/reference/sdks/server/dotnet#logging" }, "Domains": { "status": "✅", - "path": "/docs/reference/technologies/server/dotnet#domains" + "path": "/docs/reference/sdks/server/dotnet#domains" }, "Eventing": { "status": "✅", - "path": "/docs/reference/technologies/server/dotnet#eventing" + "path": "/docs/reference/sdks/server/dotnet#eventing" }, "Tracking": { "status": "✅", - "path": "/docs/reference/technologies/server/dotnet#tracking" + "path": "/docs/reference/sdks/server/dotnet#tracking" }, "Transaction Context Propagation": { "status": "✅", - "path": "/docs/reference/technologies/server/dotnet#transaction-context-propagation" + "path": "/docs/reference/sdks/server/dotnet#transaction-context-propagation" }, "Shutdown": { "status": "✅", - "path": "/docs/reference/technologies/server/dotnet#shutdown" + "path": "/docs/reference/sdks/server/dotnet#shutdown" }, "Extending": { "status": "✅", - "path": "/docs/reference/technologies/server/dotnet#extending" + "path": "/docs/reference/sdks/server/dotnet#extending" + }, + "Multi-Provider": { + "status": "❓", + "path": "/docs/reference/sdks/server/dotnet" } } }, { "name": "Go", - "path": "/docs/reference/technologies/server/go", + "path": "/docs/reference/sdks/server/go", "category": "Server", "release": { - "href": "https://github.com/open-feature/go-sdk/releases/tag/v1.16.0", - "version": "1.16.0", + "href": "https://github.com/open-feature/go-sdk/releases/tag/v1.17.1", + "version": "1.17.1", "stable": true }, "spec": { @@ -183,53 +195,57 @@ "features": { "Providers": { "status": "✅", - "path": "/docs/reference/technologies/server/go#providers" + "path": "/docs/reference/sdks/server/go#providers" }, "Targeting": { "status": "✅", - "path": "/docs/reference/technologies/server/go#targeting" + "path": "/docs/reference/sdks/server/go#targeting" }, "Hooks": { "status": "✅", - "path": "/docs/reference/technologies/server/go#hooks" + "path": "/docs/reference/sdks/server/go#hooks" }, "Logging": { "status": "✅", - "path": "/docs/reference/technologies/server/go#logging" + "path": "/docs/reference/sdks/server/go#logging" }, "Domains": { "status": "✅", - "path": "/docs/reference/technologies/server/go#domains" + "path": "/docs/reference/sdks/server/go#domains" }, "Eventing": { "status": "✅", - "path": "/docs/reference/technologies/server/go#eventing" + "path": "/docs/reference/sdks/server/go#eventing" }, "Tracking": { "status": "✅", - "path": "/docs/reference/technologies/server/go#tracking" + "path": "/docs/reference/sdks/server/go#tracking" }, "Transaction Context Propagation": { "status": "✅", - "path": "/docs/reference/technologies/server/go#transaction-context-propagation" + "path": "/docs/reference/sdks/server/go#transaction-context-propagation" }, "Shutdown": { "status": "✅", - "path": "/docs/reference/technologies/server/go#shutdown" + "path": "/docs/reference/sdks/server/go#shutdown" }, "Extending": { "status": "✅", - "path": "/docs/reference/technologies/server/go#extending" + "path": "/docs/reference/sdks/server/go#extending" + }, + "Multi-Provider": { + "status": "❓", + "path": "/docs/reference/sdks/server/go" } } }, { "name": "Python", - "path": "/docs/reference/technologies/server/python", + "path": "/docs/reference/sdks/server/python", "category": "Server", "release": { - "href": "https://github.com/open-feature/python-sdk/releases/tag/v0.8.3", - "version": "0.8.3", + "href": "https://github.com/open-feature/python-sdk/releases/tag/v0.8.4", + "version": "0.8.4", "stable": false }, "spec": { @@ -239,53 +255,57 @@ "features": { "Providers": { "status": "✅", - "path": "/docs/reference/technologies/server/python#providers" + "path": "/docs/reference/sdks/server/python#providers" }, "Targeting": { "status": "✅", - "path": "/docs/reference/technologies/server/python#targeting" + "path": "/docs/reference/sdks/server/python#targeting" }, "Hooks": { "status": "✅", - "path": "/docs/reference/technologies/server/python#hooks" + "path": "/docs/reference/sdks/server/python#hooks" }, "Logging": { "status": "✅", - "path": "/docs/reference/technologies/server/python#logging" + "path": "/docs/reference/sdks/server/python#logging" }, "Domains": { "status": "✅", - "path": "/docs/reference/technologies/server/python#domains" + "path": "/docs/reference/sdks/server/python#domains" }, "Eventing": { "status": "✅", - "path": "/docs/reference/technologies/server/python#eventing" + "path": "/docs/reference/sdks/server/python#eventing" }, "Tracking": { "status": "❓", - "path": "/docs/reference/technologies/server/python" + "path": "/docs/reference/sdks/server/python" }, "Transaction Context Propagation": { "status": "✅", - "path": "/docs/reference/technologies/server/python#transaction-context-propagation" + "path": "/docs/reference/sdks/server/python#transaction-context-propagation" }, "Shutdown": { "status": "✅", - "path": "/docs/reference/technologies/server/python#shutdown" + "path": "/docs/reference/sdks/server/python#shutdown" }, "Extending": { "status": "✅", - "path": "/docs/reference/technologies/server/python#extending" + "path": "/docs/reference/sdks/server/python#extending" + }, + "Multi-Provider": { + "status": "❓", + "path": "/docs/reference/sdks/server/python" } } }, { "name": "PHP", - "path": "/docs/reference/technologies/server/php", + "path": "/docs/reference/sdks/server/php", "category": "Server", "release": { - "href": "https://github.com/open-feature/php-sdk/releases/tag/2.1.0", - "version": "2.1.0", + "href": "https://github.com/open-feature/php-sdk/releases/tag/2.1.1", + "version": "2.1.1", "stable": true }, "spec": { @@ -295,53 +315,57 @@ "features": { "Providers": { "status": "✅", - "path": "/docs/reference/technologies/server/php#providers" + "path": "/docs/reference/sdks/server/php#providers" }, "Targeting": { "status": "✅", - "path": "/docs/reference/technologies/server/php#targeting" + "path": "/docs/reference/sdks/server/php#targeting" }, "Hooks": { "status": "✅", - "path": "/docs/reference/technologies/server/php#hooks" + "path": "/docs/reference/sdks/server/php#hooks" }, "Logging": { "status": "✅", - "path": "/docs/reference/technologies/server/php#logging" + "path": "/docs/reference/sdks/server/php#logging" }, "Domains": { "status": "❌", - "path": "/docs/reference/technologies/server/php#named-clients" + "path": "/docs/reference/sdks/server/php#named-clients" }, "Eventing": { "status": "⚠️", - "path": "/docs/reference/technologies/server/php#eventing" + "path": "/docs/reference/sdks/server/php#eventing" }, "Tracking": { "status": "❓", - "path": "/docs/reference/technologies/server/php" + "path": "/docs/reference/sdks/server/php" }, "Transaction Context Propagation": { "status": "❓", - "path": "/docs/reference/technologies/server/php" + "path": "/docs/reference/sdks/server/php" }, "Shutdown": { "status": "❌", - "path": "/docs/reference/technologies/server/php#shutdown" + "path": "/docs/reference/sdks/server/php#shutdown" }, "Extending": { "status": "✅", - "path": "/docs/reference/technologies/server/php#extending" + "path": "/docs/reference/sdks/server/php#extending" + }, + "Multi-Provider": { + "status": "❓", + "path": "/docs/reference/sdks/server/php" } } }, { "name": "Web", - "path": "/docs/reference/technologies/client/web", + "path": "/docs/reference/sdks/client/web", "category": "Client", "release": { - "href": "https://github.com/open-feature/js-sdk/releases/tag/web-sdk-v1.6.2", - "version": "1.6.2", + "href": "https://github.com/open-feature/js-sdk/releases/tag/web-sdk-v1.7.2", + "version": "1.7.2", "stable": true }, "spec": { @@ -351,45 +375,49 @@ "features": { "Providers": { "status": "✅", - "path": "/docs/reference/technologies/client/web#providers" + "path": "/docs/reference/sdks/client/web#providers" }, "Targeting": { "status": "✅", - "path": "/docs/reference/technologies/client/web#targeting-and-context" + "path": "/docs/reference/sdks/client/web#targeting-and-context" }, "Hooks": { "status": "✅", - "path": "/docs/reference/technologies/client/web#hooks" + "path": "/docs/reference/sdks/client/web#hooks" }, "Logging": { "status": "✅", - "path": "/docs/reference/technologies/client/web#logging" + "path": "/docs/reference/sdks/client/web#logging" }, "Domains": { "status": "✅", - "path": "/docs/reference/technologies/client/web#domains" + "path": "/docs/reference/sdks/client/web#domains" }, "Eventing": { "status": "✅", - "path": "/docs/reference/technologies/client/web#eventing" + "path": "/docs/reference/sdks/client/web#eventing" }, "Tracking": { "status": "✅", - "path": "/docs/reference/technologies/client/web#tracking" + "path": "/docs/reference/sdks/client/web#tracking" }, "Shutdown": { "status": "✅", - "path": "/docs/reference/technologies/client/web#shutdown" + "path": "/docs/reference/sdks/client/web#shutdown" }, "Extending": { "status": "✅", - "path": "/docs/reference/technologies/client/web#extending" + "path": "/docs/reference/sdks/client/web#extending" + }, + "Multi-Provider": { + "status": "✅", + "path": "/docs/reference/sdks/client/web#multi-provider" } } }, { "name": "Kotlin", - "path": "/docs/reference/technologies/client/kotlin", + "path": "/docs/reference/sdks/client/kotlin", "category": "Client", "release": { "href": "https://github.com/open-feature/kotlin-sdk/releases/tag/v0.7.0", @@ -403,49 +431,53 @@ "features": { "Providers": { "status": "✅", - "path": "/docs/reference/technologies/client/kotlin#providers" + "path": "/docs/reference/sdks/client/kotlin#providers" }, "Targeting": { "status": "✅", - "path": "/docs/reference/technologies/client/kotlin#targeting" + "path": "/docs/reference/sdks/client/kotlin#targeting" }, "Hooks": { "status": "✅", - "path": "/docs/reference/technologies/client/kotlin#hooks" + "path": "/docs/reference/sdks/client/kotlin#hooks" }, "Logging": { "status": "❌", - "path": "/docs/reference/technologies/client/kotlin#logging" + "path": "/docs/reference/sdks/client/kotlin#logging" }, "Domains": { "status": "❌", - "path": "/docs/reference/technologies/client/kotlin#named-clients" + "path": "/docs/reference/sdks/client/kotlin#domains" }, "Eventing": { "status": "✅", - "path": "/docs/reference/technologies/client/kotlin#eventing" + "path": "/docs/reference/sdks/client/kotlin#eventing" }, "Tracking": { "status": "✅", - "path": "/docs/reference/technologies/client/kotlin#tracking" + "path": "/docs/reference/sdks/client/kotlin#tracking" }, "Shutdown": { "status": "✅", - "path": "/docs/reference/technologies/client/kotlin#shutdown" + "path": "/docs/reference/sdks/client/kotlin#shutdown" }, "Extending": { - "status": "⚠️", - "path": "/docs/reference/technologies/client/kotlin#extending" + "status": "✅", + "path": "/docs/reference/sdks/client/kotlin#extending" + }, + "Multi-Provider": { + "status": "✅", + "path": "/docs/reference/sdks/client/kotlin#multi-provider" } } }, { "name": "iOS", - "path": "/docs/reference/technologies/client/swift", + "path": "/docs/reference/sdks/client/swift", "category": "Client", "release": { - "href": "https://github.com/open-feature/swift-sdk/releases/tag/0.4.0", - "version": "0.4.0", + "href": "https://github.com/open-feature/swift-sdk/releases/tag/0.5.0", + "version": "0.5.0", "stable": false }, "spec": { @@ -455,49 +487,53 @@ "features": { "Providers": { "status": "✅", - "path": "/docs/reference/technologies/client/swift#providers" + "path": "/docs/reference/sdks/client/swift#providers" }, "Targeting": { "status": "✅", - "path": "/docs/reference/technologies/client/swift#targeting" + "path": "/docs/reference/sdks/client/swift#targeting" }, "Hooks": { "status": "✅", - "path": "/docs/reference/technologies/client/swift#hooks" + "path": "/docs/reference/sdks/client/swift#hooks" }, "Logging": { "status": "❌", - "path": "/docs/reference/technologies/client/swift#logging" + "path": "/docs/reference/sdks/client/swift#logging" }, "Domains": { - "status": "❓", - "path": "/docs/reference/technologies/client/swift" + "status": "❌", + "path": "/docs/reference/sdks/client/swift#domains" }, "Eventing": { "status": "✅", - "path": "/docs/reference/technologies/client/swift#eventing" + "path": "/docs/reference/sdks/client/swift#eventing" }, "Tracking": { - "status": "❌", - "path": "/docs/reference/technologies/client/swift#tracking" + "status": "✅", + "path": "/docs/reference/sdks/client/swift#tracking" }, "Shutdown": { "status": "❌", - "path": "/docs/reference/technologies/client/swift#shutdown" + "path": "/docs/reference/sdks/client/swift#shutdown" }, "Extending": { "status": "✅", - "path": "/docs/reference/technologies/client/swift#extending" + "path": "/docs/reference/sdks/client/swift#extending" + }, + "Multi-Provider": { + "status": "❓", + "path": "/docs/reference/sdks/client/swift" } } }, { "name": "Ruby", - "path": "/docs/reference/technologies/server/ruby", + "path": "/docs/reference/sdks/server/ruby", "category": "Server", "release": { - "href": "https://github.com/open-feature/ruby-sdk/releases/tag/v0.4.0", - "version": "0.4.0", + "href": "https://github.com/open-feature/ruby-sdk/releases/tag/v0.5.0", + "version": "0.5.0", "stable": false }, "spec": { @@ -507,53 +543,57 @@ "features": { "Providers": { "status": "✅", - "path": "/docs/reference/technologies/server/ruby#providers" + "path": "/docs/reference/sdks/server/ruby#providers" }, "Targeting": { "status": "✅", - "path": "/docs/reference/technologies/server/ruby#targeting" + "path": "/docs/reference/sdks/server/ruby#targeting" }, "Hooks": { "status": "⚠️", - "path": "/docs/reference/technologies/server/ruby#hooks" + "path": "/docs/reference/sdks/server/ruby#hooks" }, "Logging": { "status": "❌", - "path": "/docs/reference/technologies/server/ruby#logging" + "path": "/docs/reference/sdks/server/ruby#logging" }, "Domains": { "status": "✅", - "path": "/docs/reference/technologies/server/ruby#domains" + "path": "/docs/reference/sdks/server/ruby#domains" }, "Eventing": { - "status": "❌", - "path": "/docs/reference/technologies/server/ruby#eventing" + "status": "✅", + "path": "/docs/reference/sdks/server/ruby#eventing" }, "Tracking": { "status": "❓", - "path": "/docs/reference/technologies/server/ruby" + "path": "/docs/reference/sdks/server/ruby" }, "Transaction Context Propagation": { "status": "❌", - "path": "/docs/reference/technologies/server/ruby#transaction-context-propagation" + "path": "/docs/reference/sdks/server/ruby#transaction-context-propagation" }, "Shutdown": { "status": "⚠️", - "path": "/docs/reference/technologies/server/ruby#shutdown" + "path": "/docs/reference/sdks/server/ruby#shutdown" }, "Extending": { "status": "⚠️", - "path": "/docs/reference/technologies/server/ruby#extending" + "path": "/docs/reference/sdks/server/ruby#extending" + }, + "Multi-Provider": { + "status": "❓", + "path": "/docs/reference/sdks/server/ruby" } } }, { "name": "Dart", - "path": "/docs/reference/technologies/server/dart", + "path": "/docs/reference/sdks/server/dart", "category": "Server", "release": { - "href": "https://github.com/open-feature/dart-server-sdk/releases/tag/v0.0.13", - "version": "0.0.13", + "href": "https://github.com/open-feature/dart-server-sdk/releases/tag/v0.0.16", + "version": "0.0.16", "stable": false }, "spec": { @@ -563,52 +603,56 @@ "features": { "Providers": { "status": "✅", - "path": "/docs/reference/technologies/server/dart#providers" + "path": "/docs/reference/sdks/server/dart#providers" }, "Targeting": { "status": "✅", - "path": "/docs/reference/technologies/server/dart#targeting" + "path": "/docs/reference/sdks/server/dart#targeting" }, "Hooks": { "status": "✅", - "path": "/docs/reference/technologies/server/dart#hooks" + "path": "/docs/reference/sdks/server/dart#hooks" }, "Logging": { "status": "✅", - "path": "/docs/reference/technologies/server/dart#logging" + "path": "/docs/reference/sdks/server/dart#logging" }, "Domains": { "status": "✅", - "path": "/docs/reference/technologies/server/dart#domains" + "path": "/docs/reference/sdks/server/dart#domains" }, "Eventing": { "status": "✅", - "path": "/docs/reference/technologies/server/dart#eventing" + "path": "/docs/reference/sdks/server/dart#eventing" }, "Tracking": { "status": "❓", - "path": "/docs/reference/technologies/server/dart" + "path": "/docs/reference/sdks/server/dart" }, "Transaction Context Propagation": { "status": "✅", - "path": "/docs/reference/technologies/server/dart#transaction-context-propagation" + "path": "/docs/reference/sdks/server/dart#transaction-context-propagation" }, "Shutdown": { "status": "✅", - "path": "/docs/reference/technologies/server/dart#shutdown" + "path": "/docs/reference/sdks/server/dart#shutdown" }, "Extending": { "status": "✅", - "path": "/docs/reference/technologies/server/dart#extending" + "path": "/docs/reference/sdks/server/dart#extending" + }, + "Multi-Provider": { + "status": "❓", + "path": "/docs/reference/sdks/server/dart" } } }, { "name": "Rust", - "path": "/docs/reference/technologies/server/rust", + "path": "/docs/reference/sdks/server/rust", "category": "Server", "release": { - "href": "https://github.com/open-feature/rust-sdk/releases/tag/v0.2.7", + "href": "https://github.com/open-feature/rust-sdk/releases/tag/open-feature-v0.2.7", "version": "0.2.7", "stable": false }, @@ -619,43 +663,47 @@ "features": { "Providers": { "status": "✅", - "path": "/docs/reference/technologies/server/rust#providers" + "path": "/docs/reference/sdks/server/rust#providers" }, "Targeting": { "status": "✅", - "path": "/docs/reference/technologies/server/rust#targeting" + "path": "/docs/reference/sdks/server/rust#targeting" }, "Hooks": { "status": "✅", - "path": "/docs/reference/technologies/server/rust#hooks" + "path": "/docs/reference/sdks/server/rust#hooks" }, "Logging": { "status": "✅", - "path": "/docs/reference/technologies/server/rust#logging" + "path": "/docs/reference/sdks/server/rust#logging" }, "Domains": { "status": "✅", - "path": "/docs/reference/technologies/server/rust#named-clients" + "path": "/docs/reference/sdks/server/rust#named-clients" }, "Eventing": { "status": "❌", - "path": "/docs/reference/technologies/server/rust#eventing" + "path": "/docs/reference/sdks/server/rust#eventing" }, "Tracking": { "status": "❓", - "path": "/docs/reference/technologies/server/rust" + "path": "/docs/reference/sdks/server/rust" }, "Transaction Context Propagation": { "status": "❓", - "path": "/docs/reference/technologies/server/rust" + "path": "/docs/reference/sdks/server/rust" }, "Shutdown": { "status": "✅", - "path": "/docs/reference/technologies/server/rust#shutdown" + "path": "/docs/reference/sdks/server/rust#shutdown" }, "Extending": { "status": "✅", - "path": "/docs/reference/technologies/server/rust#extending" + "path": "/docs/reference/sdks/server/rust#extending" + }, + "Multi-Provider": { + "status": "❓", + "path": "/docs/reference/sdks/server/rust" } } } diff --git a/src/datasets/sdks/swift.ts b/src/datasets/sdks/swift.ts index ae737496b..cd170330e 100644 --- a/src/datasets/sdks/swift.ts +++ b/src/datasets/sdks/swift.ts @@ -8,5 +8,5 @@ export const Swift: SDK = { repo: 'swift-sdk', logoKey: 'ios-no-fill.svg', technology: 'Swift', - href: '/docs/reference/technologies/client/swift', + href: '/docs/reference/sdks/client/swift', }; diff --git a/src/datasets/sdks/web.ts b/src/datasets/sdks/web.ts index 7061c0acc..55a4b0b02 100644 --- a/src/datasets/sdks/web.ts +++ b/src/datasets/sdks/web.ts @@ -10,5 +10,5 @@ export const Web: SDK = { folder: '/packages/web', logoKey: 'web-no-fill.svg', technology: 'JavaScript', - href: '/docs/reference/technologies/client/web', + href: '/docs/reference/sdks/client/web', }; diff --git a/src/datasets/support/commercial-support.ts b/src/datasets/support/commercial-support.ts index 217f61f55..0ea01ede5 100644 --- a/src/datasets/support/commercial-support.ts +++ b/src/datasets/support/commercial-support.ts @@ -4,6 +4,7 @@ import KameleoonSvg from '@site/static/img/vendors/kameleoon.svg'; import DevCycleSvg from '@site/static/img/vendors/devcycle.svg'; import FliptSvg from '@site/static/img/vendors/flipt.svg'; import FlagsmithSvg from '@site/static/img/vendors/flagsmith.svg'; +import HarnessSvg from '@site/static/img/vendors/harness.svg'; import LaunchDarklySvg from '@site/static/img/vendors/launchdarkly.svg'; import TgglSvg from '@site/static/img/vendors/tggl.svg'; import GoffSvg from '@site/static/img/vendors/gofeatureflag.svg'; @@ -51,6 +52,11 @@ export const CommercialSupportList: CommercialSupportType[] = [ href: 'https://gofeatureflag.org/docs/openfeature_sdk/sdk', svg: GoffSvg, }, + { + name: 'Harness Feature Management & Experimentation', + href: 'https://developer.harness.io/docs/feature-management-experimentation/sdks-and-infrastructure/openfeature', + svg: HarnessSvg, + }, { name: 'Kameleoon', href: 'https://developers.kameleoon.com/feature-management-and-experimentation/open-feature-providers/', diff --git a/src/datasets/support/training.ts b/src/datasets/support/training.ts deleted file mode 100644 index e015d5c12..000000000 --- a/src/datasets/support/training.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { IconDefinition as BrandsIconDefinition } from '@fortawesome/free-brands-svg-icons'; -import { IconDefinition as FreeIconDefinition } from '@fortawesome/free-solid-svg-icons'; -import { faYoutube } from '@fortawesome/free-brands-svg-icons'; - -type ResourcesType = { - title: string; - description?: string; - href: string; - iconDefinition?: BrandsIconDefinition | FreeIconDefinition; -}; - -export const TrainingResources: ResourcesType[] = [ - { - title: 'OpenFeature Fundamentals', - description: 'An introduction to the core concepts of OpenFeature', - href: 'https://www.youtube.com/watch?v=heQ83k15ZE4&list=PLiQt8D1ofl8zs2zoiMNI8WRdNQ8GUy84I', - iconDefinition: faYoutube, - }, -]; diff --git a/src/datasets/types.ts b/src/datasets/types.ts index 9fdf997bc..30f3e9092 100644 --- a/src/datasets/types.ts +++ b/src/datasets/types.ts @@ -46,7 +46,7 @@ export type SdkCompatibility = { /** * The path in the docs to the SDK * - * @example /docs/reference/technologies/server/java + * @example /docs/reference/sdks/server/java */ path: string; /** @@ -101,7 +101,7 @@ export type SdkCompatibility = { /** * The path to the SDK doc with an anchor to the specific feature. * - * @example /docs/reference/technologies/server/java#providers + * @example /docs/reference/sdks/server/java#providers */ path: string; }; diff --git a/src/pages/ecosystem.tsx b/src/pages/ecosystem.tsx index 4c91fe297..10eb66873 100644 --- a/src/pages/ecosystem.tsx +++ b/src/pages/ecosystem.tsx @@ -16,10 +16,17 @@ import ScrollTo from '../partials/ecosystem/scroll-to'; import type { ItemsJsOptions } from 'instantsearch-itemsjs-adapter/lib/itemsjsInterface'; import type { InstantSearchOptions } from 'instantsearch.js'; +import { ECOSYSTEM_SDKS } from '../datasets/sdks/ecosystem'; +import { ECOSYSTEM_PROVIDERS } from '../datasets/providers'; -const VENDORS_SHOWN_AS_FACET = 30; +const VENDORS_SHOWN_AS_FACET = 20; const TECHNOLOGIES_SHOWN_AS_FACET = 20; +const TECHNOLOGY_COUNT = new Set( + ECOSYSTEM_SDKS.flatMap((sdk) => [sdk.technology, ...(sdk.parentTechnology ? [sdk.parentTechnology] : [])]), +).size; +const VENDOR_COUNT = new Set(ECOSYSTEM_PROVIDERS.map((provider) => provider.vendor)).size; + const options: ItemsJsOptions = { searchableFields: ['title', 'description', 'allTechnologies'], query: '', @@ -38,11 +45,16 @@ const options: ItemsJsOptions = { allTechnologies: { title: 'technologies', searchInField: ['technology', 'parentTechnology'], - size: TECHNOLOGIES_SHOWN_AS_FACET, + size: TECHNOLOGY_COUNT, hide_zero_doc_count: true, conjunction: false, }, - vendor: { title: 'vendors', size: VENDORS_SHOWN_AS_FACET, conjunction: false, hide_zero_doc_count: true }, + vendor: { + title: 'vendors', + size: VENDOR_COUNT, + conjunction: false, + hide_zero_doc_count: true, + }, vendorOfficial: { title: 'official', size: 2, conjunction: true }, }, }; @@ -52,6 +64,17 @@ const index = createIndex(ECOSYSTEM, options); // This doesn't appear to have any negative effects. const searchClient = getSearchClient(index) as InstantSearchOptions['searchClient']; +const SHARED_STYLES = { + count: + 'ml-2 px-2 rounded-md bg-gray-50 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10', + list: 'list-none m-0 p-0', + checkbox: 'border-solid h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500', + labelText: 'ml-3 text-sm text-content', + showMore: + 'mt-2 text-sm font-medium text-indigo-600 hover:text-indigo-500 dark:text-indigo-400 dark:hover:text-indigo-300 cursor-pointer bg-transparent border-none p-0 underline decoration-1 underline-offset-2 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 focus:rounded', + sectionDivider: 'border-0 border-solid border-t border-gray-200 py-4', +}; + export default function Ecosystem() { return ( @@ -96,72 +119,74 @@ export default function Ecosystem() { Filter -
+
Type
-
+
Category
-
+
Technology TECHNOLOGIES_SHOWN_AS_FACET} />
-
+
Vendor VENDORS_SHOWN_AS_FACET} />
-
+
Support level
diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 4851219ae..71289adec 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -2,15 +2,21 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import Layout from '@theme/Layout'; import AOS from 'aos'; import React, { useEffect } from 'react'; -import QuestionBlocks from '../partials/question-blocks'; -import FeaturesZigZag from '../partials/features-zigzag'; import HeroHome from '../partials/hero-home'; -import PageIllustration from '../partials/page-illustration'; +import ValueProposition from '../partials/value-proposition'; +import HowItWorks from '../partials/how-it-works'; +import KeyFeatures from '../partials/key-features'; +import EcosystemShowcase from '../partials/ecosystem-showcase'; +import SocialProof from '../partials/social-proof'; +import CTASection from '../partials/cta-section'; +import VideoEmbed from '../partials/video-embed'; import { useLocation } from '@docusaurus/router'; import 'aos/dist/aos.css'; import '../css/style.css'; +const WHAT_IS_OPENFEATURE_VIDEO_ID = 'heQ83k15ZE4'; + export default function Home(): JSX.Element { const location = useLocation(); const { siteConfig } = useDocusaurusContext(); @@ -19,8 +25,8 @@ export default function Home(): JSX.Element { AOS.init({ once: true, disable: 'phone', - duration: 1000, - easing: 'ease-out-sine', + duration: 700, + easing: 'ease-out-cubic', }); }); @@ -34,15 +40,14 @@ export default function Home(): JSX.Element {
- {/* Page illustration */} - - - {/* Page sections */} - - + + + + + + +
diff --git a/src/pages/support-training.tsx b/src/pages/support-training.tsx index 957a09c67..92d378c02 100644 --- a/src/pages/support-training.tsx +++ b/src/pages/support-training.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import { OpenFeatureComponentCard } from '../components/custom/OpenFeatureComponentCard'; +import { CourseCard } from '../components/custom/CourseCard'; import Layout from '@theme/Layout'; import { CommercialSupportList } from '../datasets/support/commercial-support'; -import { TrainingResources } from '../datasets/support/training'; import Link from '@docusaurus/Link'; +import lfs140Image from '@site/static/img/blog/2025-11-18-kubecon-na-recap-and-new-cncf-training/lfs140.png'; export default function Support(): JSX.Element { return ( @@ -14,15 +14,29 @@ export default function Support(): JSX.Element {

Courses

-
- {TrainingResources.map((resource) => ( - - ))} +
+ +
@@ -34,7 +48,7 @@ export default function Support(): JSX.Element { title={name} className="card card-container padding--lg dark:bg-white w-[362px] h-44 relative" > -
{'🔗'}
+
{'🔗'}
@@ -61,4 +75,3 @@ export default function Support(): JSX.Element { ); } - \ No newline at end of file diff --git a/src/partials/cta-section.tsx b/src/partials/cta-section.tsx new file mode 100644 index 000000000..32e07d5f2 --- /dev/null +++ b/src/partials/cta-section.tsx @@ -0,0 +1,97 @@ +import React from 'react'; +import Link from '@docusaurus/Link'; + +function CTASection() { + return ( +
+
+
+
+

+ Ready to standardize your feature flags? +

+

+ Join hundreds of teams already using OpenFeature. Get started with the tutorial, + explore the specification, or connect with the community. +

+ + {/* CTA cards */} +
+ +
+ + + +
+

Tutorial

+

5-minute quick start guide

+ + + +
+ + + +
+

Specification

+

Read the open standard

+ + + +
+ + + +
+

Community

+

Join us on Slack & GitHub

+ +
+ + {/* Secondary links */} +
+ + Join Slack + + | + + GitHub + + | + + Twitter + + | + + Blog + +
+
+
+
+
+ ); +} + +export default CTASection; diff --git a/src/partials/ecosystem-showcase.tsx b/src/partials/ecosystem-showcase.tsx new file mode 100644 index 000000000..ff08e9d94 --- /dev/null +++ b/src/partials/ecosystem-showcase.tsx @@ -0,0 +1,90 @@ +import React from 'react'; +import Link from '@docusaurus/Link'; +import { PROVIDERS } from '@site/src/datasets/providers'; +import { ECOSYSTEM_SDKS } from '@site/src/datasets/sdks/ecosystem'; + +const featuredProviders = PROVIDERS.filter((provider) => !provider.excludeFromLandingPage).slice(0, 18); +const sdks = ECOSYSTEM_SDKS.filter((sdk) => sdk.href.startsWith('/')); + +function EcosystemShowcase() { + return ( +
+
+
+ {/* Section header */} +
+
+ Ecosystem +
+

+ Works with your favorite tools +

+

+ 30+ providers and 10+ language SDKs — and growing every month. + Built with the industry, backed by the community. +

+
+ + {/* Provider logos grid */} +
+

+ Supported Providers +

+
+ {featuredProviders.map((provider) => { + const Icon = provider.logo; + return ( + + + + ); + })} +
+
+ + View all providers → + +
+
+ + {/* SDK language grid */} +
+

+ Official SDKs +

+
+ {sdks.map((sdk) => { + const Icon = sdk.logo; + return ( + + + + {sdk.title.replace(' SDK', '')} + + + ); + })} +
+
+
+
+
+ ); +} + +export default EcosystemShowcase; diff --git a/src/partials/ecosystem/hit.tsx b/src/partials/ecosystem/hit.tsx index 582b035dc..4b7640070 100644 --- a/src/partials/ecosystem/hit.tsx +++ b/src/partials/ecosystem/hit.tsx @@ -32,7 +32,11 @@ export default function Hit({ hit }: { hit: EcosystemElement | OFREPElement }) { {hit.parentTechnology && ( {hit.parentTechnology} )} - {hit.category} + {hit.category.map((cat) => ( + + {cat} + + ))} )} {hit.type} diff --git a/src/partials/features-zigzag.tsx b/src/partials/features-zigzag.tsx index 993578d2d..90f771f23 100644 --- a/src/partials/features-zigzag.tsx +++ b/src/partials/features-zigzag.tsx @@ -91,11 +91,11 @@ function FeaturesZigZag() {
{/* Section header */}
-
+
Open source

Community driven feature flagging

-

+

OpenFeature is an open source CNCF incubating project under the Apache 2 license. Check out the project on{' '} GitHub and consider joining the{' '} OpenFeature community! @@ -126,11 +126,11 @@ function FeaturesZigZag() {

Avoid code-level lock-in

One SDK, any backend

-

+

OpenFeature is designed to work with any feature flag management tool or in-house solution. This enables you to switch between platforms or consolidate multiple platforms much more easily.

-
    +
    • @@ -172,11 +172,11 @@ function FeaturesZigZag() { Developed with the industry

Supports your favorite tools

-

+

OpenFeature has broad industry support, and many of the top open source and commercial tools have created officially-supported providers.

-
    +
    • @@ -217,7 +217,7 @@ function FeaturesZigZag() {
      Ultimate flexibility

      Speaks your language

      -

      +

      OpenFeature supports many of the top programming languages, with more on the way.

      diff --git a/src/partials/hero-home.tsx b/src/partials/hero-home.tsx index 437ac05f0..94c5cc065 100644 --- a/src/partials/hero-home.tsx +++ b/src/partials/hero-home.tsx @@ -1,54 +1,130 @@ import React from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import Link from '@docusaurus/Link'; function HeroHome() { - const { siteConfig } = useDocusaurusContext(); return ( -
      +
      + {/* Animated gradient background */} +