diff --git a/website/docs/topics/the-anatomy-of-unleash.mdx b/website/docs/topics/the-anatomy-of-unleash.mdx
new file mode 100644
index 0000000000..7ced4d7cf5
--- /dev/null
+++ b/website/docs/topics/the-anatomy-of-unleash.mdx
@@ -0,0 +1,202 @@
+---
+title: The Anatomy of Unleash
+---
+import Figure from '@site/src/components/Figure/Figure.tsx'
+
+This guide's purpose is to give you a conceptual overview of how Unleash works. It covers the various components that exist within an Unleash system and how they interact with each other and with external applications. The diagrams are intended to help you understand the fundamental building blocks, such as [projects](../user_guide/projects.md), [environments](../user_guide/environments.md), [variants](../advanced/feature-toggle-variants.md) and, of course, [feature toggles](../reference/feature-toggles.mdx).
+
+The end of this guide presents a [short use case, explaining how you might configure Unleash](#use-case) to start working with feature toggles.
+
+
+## The global level
+
+Some things in Unleash are configured and defined on the global level. These options apply across the entire Unleash instance. The most important global configuration options for day-to-day operations are:
+
+- [API access tokens](../reference/api-tokens-and-client-keys.mdx)
+- [Projects](../user_guide/projects.md)
+- [Segments](../reference/segments.mdx)
+- [Strategy types](../user_guide/activation-strategies.md) (including [custom activation strategy types](../advanced/custom-activation-strategy.md))
+- [Tag types](../advanced/tags.md)
+- [Unleash context](../user_guide/unleash-context.md) fields (including [custom context fields](../user_guide/unleash-context.md#custom-context-fields))
+- Users, [user groups](../user_guide/rbac.md#user-groups) and [global roles](../user_guide/rbac.md)
+
+
+## Projects
+
+[**Projects**](../user_guide/projects.md) contain [feature toggles](../reference/feature-toggles.mdx) and their configurations, and a set of active [environments](../user_guide/environments.md).
+
+All Unleash instances must have at least one project at any given time. New instances get a project called “Default”.
+
+Pro and Enterprise customers can create, rename, and delete projects as they wish (as long as there is always **at least one project**). Open-source users, on the other hand, only get access to the Default project.
+
+
+
+## Environments and project environments
+
+
+
+[**Environments**](../user_guide/environments.md) in Unleash let you change how a feature toggle works in your application’s different environments. For instance, while you are developing a feature, it’s likely that you’ll want it to be available in your development environment, but not in your production environment: environments let you do that. You might also want to enable a feature for only some users in your development environment, but no users in your production environment: environments let you do that.
+
+Environments exist on two different levels within Unleash. The set of **all available environments is defined on the global level**. Additionally, **each project** can choose which of these global environments should be **available on the project level**. The set of environments available to any given project is **always a subset** of the set of globally available environments.
+
+Each project must always have **at least one** active environment.
+
+Enterprise users can create and remove environments. Open-source and Pro customers get access to two environments: **development** and **production.**
+
+Environments are adjacent to [feature toggles](../reference/feature-toggles.mdx) in Unleash: neither one contains the other, but they come together to let you define activation strategies.
+
+
+
+:::info Environments and API keys
+
+When connecting an SDK to Unleash, it's the **API key that decides which environment to** fetch features for. For legacy reasons, all Unleash SDKs accept a configuration option called `environment`, but this **does not affect the environment** at all. It is an Unleash context field and a holdover from before Unleash had native environments.
+
+:::
+
+
+## Features (feature toggles)
+
+[**Feature toggles**](../reference/feature-toggles.mdx) are at the heart of Unleash’s functionality. Feature toggles belong to projects and live next to project environments. In and of itself, a feature toggle doesn’t do anything. You must assign [**activation strategies**](../user_guide/activation-strategies.md) to it for it to start taking effect.
+
+When creating a feature toggle, you must assign a unique (across your Unleash instance) name, a [feature toggle type](../advanced/feature-toggle-types.md), a [project](../user_guide/projects.md) it belongs to, and an optional description. Everything except for the name can be changed later.
+
+
+
+## Activation strategies
+
+
+
+[**Activation strategies**](../user_guide/activation-strategies.md) (or just **strategies** for short) are the part of feature toggles that tell Unleash **who should get a feature**. An activation strategy is assigned to **one **feature toggle in **one **environment.
+
+When you check a [feature toggle](../reference/feature-toggles.mdx) in an application, the following decides the result:
+1. Is the toggle active in the current environment? If not, it will be disabled.
+2. If the toggle **is** active in the current environment, the toggle’s strategies decide the result. As long as **at least one** of a toggle’s strategies resolve to true for the current context (user or application), then the toggle will be considered enabled. In other words, if you have a hundred strategies and ninety-nine of them resolve to false, but one of them resolves to true, then the toggle is enabled.
+
+Activation strategies tie feature toggles and [environments](../user_guide/environments.md) together. When you assign an activation strategy to a feature toggle, you do so in one environment at a time. You can assign the same strategy to the same toggle in different environments, but they will be different instances of the same strategy, and do not stay in sync. Unleash also lets you copy strategies from one environment to another.
+
+Unleash comes with a number of strategies built in (refer the [activation strategies documentation](../user_guide/activation-strategies.md) for more information on those). You can also create your own [custom activation strategies](../advanced/custom-activation-strategy.md) if you need them. All strategies can be further augmented by [**strategy constraints**](../advanced/strategy-constraints.md).
+
+
+
+
+
+
+## Strategy constraints
+
+[**Strategy constraints**](../advanced/strategy-constraints.md) (or just **constraints**) help you fine-tune your strategies. They are an extra layer of prerequisites that help you narrow the audience of a strategy down. Strategy constraints are applied to [**activation strategies**](../user_guide/activation-strategies.md).
+
+For example, if you wanted to roll a feature out to 50% of users with **a specific email domain **(such as “@mycompany.com”), then strategy constraints would let you target only users with that email domain.
+
+Constraints can also be used for more general purposes, such as timing feature releases or releasing features in specific regions.
+
+An activation strategy can have as many constraints as you want. When an activation strategy has multiple constraints, then **every constraint **must be satisfied for the strategy to be evaluated. So if you have two constraints: one that says users must have an “@mycompany.com” email address and one that says users must have signed up for a beta program, then the strategy would **only be evaluated for users with @mycompany.com emails that have signed up for the program**.
+
+:::tip Strategies and constraints
+
+Feature toggle strategies are **permissive**: As long as **one** strategy resolves to true, the feature is considered enabled. On the other hand, constrains are **restrictive**: for a given strategy, **all** constraints must be met for it to resolve to true.
+
+We can exemplify this difference with the logical operators AND and OR:
+- For a feature toggle, if Strategy1 OR Strategy2 OR .. OR StrategyN is true, **then the feature is enabled**.
+- For a strategy, it can be evaluated **if and only if** Constraint1 AND Constraint2 AND .. AND ConstraintN are met.
+
+Note that even if all the constraints are met, the strategy itself might not resolve to true: that will depend on the strategy and the provided context.
+
+:::
+
+
+You can define constraints on whatever properties you want in your [Unleash context](../user_guide/unleash-context.md).
+
+Constraints are applied to individual strategies and do not stay in sync with each other. When you need to have the same constraints applied to multiple strategies and need those constraints to stay in sync, use [**segments**](../reference/segments.mdx).
+
+
+
+## Segments
+
+[**Segments**](../reference/segments.mdx) add extra functionality on top of [**strategy constraints**](../advanced/strategy-constraints.md). A segment is a reusable collection of strategy constraints with a name and an optional description. When you apply a segment to a [strategy](../user_guide/activation-strategies.md), the strategy will be evaluated as if all of the segment's constraints were applied to it.
+
+Segments let you apply a set of constraints to multiple strategies **and** keep the constraints in sync between those strategies. Whenever you apply a segment to a strategy, you essentially create a **reference** to that segment. This means that whenever you change the segment by adding, removing, or changing constraints, this change propagates to all the strategies that reference this segment.
+
+You can apply multiple segments to a strategy. Much like with constraints, **every segment** needs **every constraint** to be satisfied for the strategy to be evaluated. If you also have other constraints on the strategy, then those must also be satisfied.
+
+Segments are only available to Pro and Enterprise users.
+
+
+
+## Variants and feature toggle payloads
+
+By default, a [feature toggle](../reference/feature-toggles.mdx) in Unleash only tells you whether a feature is enabled or disabled, but you can also add more information to your toggles by using [**feature toggle variants**](../advanced/feature-toggle-variants.md). Variants also allow you to run [A/B testing experiments](a-b-testing.md).
+
+Feature toggles are designed to let you decide which users get access to a feature. Variants are designed to let you decide **which version** of the feature a user gets access to. For instance, if user A is part of your beta testing program and gets access to a new beta feature, then you can use variants to decide whether they should get the red version or the green version of the feature.
+
+When you create new variants for a feature, they must be given a name and a **weighting** indicating how many users should see this particular variant of the feature. They can also be given a **payload**.
+
+You can use the variant payload to attach arbitrary data to a variant. Variants can have different kinds of payloads.
+
+A feature toggle can have as many variants as you want. Importantly, variants are independent of [environments](../user_guide/environments.md). In other words: you’ll always have the exact same variants with the exact same weightings and the exact same payloads in all environments.
+
+
+
+## Use case: changing website colors {#use-case}
+
+Using the concepts we have looked at in the previous sections, let’s create a hypothetical case and see how Unleash would solve it.
+
+**Problem statement:** You have an existing website with a **red** color scheme, but you’re feeling a bit adventurous and would like to try and see if changing it to a blue color scheme would be better.
+
+**Current state:** You have an existing website that gets server-side rendered and you have a newly created instance of Unleash.
+
+### Configuring Unleash for development
+
+Assuming you have a brand new Unleash instance, you already have the “Default” project and the “Development” and “Production” environments available. That’s going to be all you need for now.
+
+First things first, in the Default project, you create a new feature toggle, called “new-color-scheme” (toggle names have to be URL-friendly, so no spaces allowed!).
+
+Because you’d like to see the new color scheme while you’re developing it, you assign a “standard” strategy to the new-color-scheme toggle in the development environment and turn it on.
+
+### In your application
+
+You configure an [Unleash SDK for your server](../sdks/index.md) to communicate with Unleash. When rendering the page, you check the state of the new-color-scheme feature and render a different stylesheet based on the results.
+
+In pseudocode (loosely based on the [Node.js SDK](../sdks/node.md)), that might look like this:
+
+```js
+if (unleash.isEnabled(“new-color-scheme”)) {
+ // load stylesheet with new color scheme
+} else {
+ // load stylesheet with old color scheme
+}
+```
+
+And with that, the new color scheme is now live in your development environment. Because there aren’t any strategies defined in the production environment yet, the feature is not active, and everything is as it was.
+
+
+### Rolling out the feature to users
+
+When you’re happy with the new color scheme, you decide to start rolling it out to users. But you want it to go out to only a small number of users at first, so that you can get some feedback while rolling out.
+
+You decide to add a _gradual rollout_ strategy to the new-color-scheme feature in the production environment. Because you want to start small, you set the rollout percentage to 5%.
+
+As soon as you enable the production environment, the feature gets rolled out to 5% of your users (assuming you’ve deployed the code to production).
+
+
+### Adding variants
+
+While you were developing the new color scheme, you also dabbled a bit with other colors in addition to blue: green and purple might be nice too! So you decide to create two extra color schemes that you’re happy with. But you’d like to hear what your users think too, so you need to roll it out to them somehow.
+
+You decide to use feature toggle variants to differentiate between the different themes, creating three variants: blue, green, and purple. You want each of them to roll out to the same number of users, so you leave them equally weighted.
+
+```js
+
+const theme = unleash.getVariant(“new-color-scheme”).name;
+
+if (theme === “green”) {
+ // load stylesheet with green color scheme
+} else if (theme === “blue”) {
+ // load stylesheet with blue color scheme
+} else if (theme === “purple”) {
+ // load stylesheet with purple color scheme
+} else {
+ // load stylesheet with old color scheme
+}
+```
+
+Now users that are included in the gradual rollout will get one of the three themes. Users that aren’t included get the old theme.
diff --git a/website/sidebars.js b/website/sidebars.js
index 527b4599ca..9f22bb96ae 100644
--- a/website/sidebars.js
+++ b/website/sidebars.js
@@ -28,6 +28,23 @@ module.exports = {
'user_guide/quickstart',
],
},
+ {
+ label: 'Topic guides',
+ collapsed: false,
+ type: 'category',
+ link: {
+ type: 'generated-index',
+ title: 'Topic guides',
+ description:
+ 'Discussions, explanations, and explorations regarding topics related to Unleash.',
+ slug: '/topics',
+ },
+ items: [
+ 'topics/the-anatomy-of-unleash',
+ 'topics/a-b-testing',
+ 'topics/proxy-hosting',
+ ],
+ },
{
label: 'How-to guides',
collapsed: false,
@@ -305,18 +322,5 @@ module.exports = {
},
],
},
- {
- label: 'Topic guides',
- collapsed: false,
- type: 'category',
- link: {
- type: 'generated-index',
- title: 'Topic guides',
- description:
- 'Discussions, explanations, and explorations regarding topics related to Unleash.',
- slug: '/topics',
- },
- items: ['topics/a-b-testing', 'topics/proxy-hosting'],
- },
],
};
diff --git a/website/src/components/Figure/Figure.stories.tsx b/website/src/components/Figure/Figure.stories.tsx
new file mode 100644
index 0000000000..fc9ac86b07
--- /dev/null
+++ b/website/src/components/Figure/Figure.stories.tsx
@@ -0,0 +1,30 @@
+import React from 'react';
+import Component from './Figure';
+import Layout from '@theme/Layout';
+import { BrowserRouter } from 'react-router-dom';
+
+export default {
+ title: 'Figure',
+ component: Component,
+};
+
+const Template = (args) => (
+
+
+
+
+
+);
+
+export const WithCaption = Template.bind({});
+WithCaption.args = {
+ img: '/img/anatomy-of-unleash-constraint.png',
+ caption: 'This explanatory caption is visible to everyone.',
+};
+
+export const WithCaptionAndAlt = Template.bind({});
+WithCaption.args = {
+ img: '/img/anatomy-of-unleash-constraint.png',
+ caption: 'This explanatory caption is visible to everyone.',
+ alt: "This alt text is read out by screen readers and displayed if the image doesn't load",
+};
diff --git a/website/src/components/Figure/Figure.tsx b/website/src/components/Figure/Figure.tsx
new file mode 100644
index 0000000000..681a2f4098
--- /dev/null
+++ b/website/src/components/Figure/Figure.tsx
@@ -0,0 +1,90 @@
+/**
+ This component displays a figure with an accompanying figure caption. Use it
+ to display diagrams, charts, and other images that have an explanatory
+ caption that should be visible to everyone.
+
+ For some info regarding alt text vs fig captions, see this stack overflow
+ response from a blind user (available at
+ https://stackoverflow.com/questions/58447538/accessibility-difference-between-img-alt-and-figcaption):
+
+ I'm a blind user. I would say that there are two big categories of images on the web:
+
+ 1. Functional images
+ 2. Illustrative images a.k.a. figures
+
+ AS the name says, figcaption is a caption for a figure. The caption is
+ always visible by everybody, not only blind people. Figures are images that
+ can be found in a book, an article, or whatever more or less long paragraphs
+ of text. Most of the time, figures are purely illustrative.
+
+ When you use figcaption, the alt attribute should probably be empty:
+
+ - Copying the text of the figcaption into the alt attribute, or any
+ shortened version, is almost always useless: the screen reader will read
+ twice the same or almost the same information, and it's worth absolutely
+ nothing
+
+ - You may think that the alt attribute could be useful for a longer
+ description of the image, that wouldn't fit in the figcaption; for example
+ a detailed description of a chart or a diagram. But in fact, this kind of
+ description is better below the image or in another page (then available
+ for everybody), rather than in the alt attribute. The alt attribute should
+ normally remain short.
+
+ - You may think that the figcaption is useless and only set the alt
+ attribute to something. Example: "Photo with Alice on the left, Bob on the
+ right". But in fact sighted people could as well find this information
+ useful, if they don't know Alice and Bob for example. So it could be
+ interesting to move this description to the figcaption, so that everybody
+ benefits from it and not only blind people.
+
+ Now, the biggest case when you won't use figure/figcaption is when images
+ are functional: a button taht can be clicked, an icon with a precise
+ meaning, etc. The basic rules for alt texts of functional images are:
+
+ - If you can interact with the image to perform actions (click, etc.), or if
+ the icon conveys an information, then you must set a non-empty alt. It
+ must be a function description, not a objective description of the image.
+
+ Example 1: "Go back" is good, while "Blue left arrow" is bad.
+ Example 2: "Unread message" is good, while "Closed enveloppe" is bad
+
+ - Otherwise, if the image provide no interaction and if it doesn't convey
+ any information, then it is illustrative; the alt should be empty in that
+ case.
+
+ ------
+
+ However, even when using fig captions, there **may** be times when also
+ using an alt is appropriate, which is why it's an optional attribute on
+ this component. However, if you do use it, make sure it conveys
+ **separate** information to what the fig caption does.
+
+
+**/
+
+import React from 'react';
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+import './styles.module.css';
+
+type Props = {
+ // An optional alt text, if the caption does not already convey all relevant
+ // information.
+ alt?: string;
+ // The figure caption, visible to everyone
+ caption: string;
+ // the path to the image, starting with `/img/`. Example: /img/image.png
+ img: string;
+};
+
+const Component: React.FC = ({ img, alt, caption }) => {
+ return (
+
+ );
+};
+
+export default Component;
diff --git a/website/src/components/Figure/styles.module.css b/website/src/components/Figure/styles.module.css
new file mode 100644
index 0000000000..8079842656
--- /dev/null
+++ b/website/src/components/Figure/styles.module.css
@@ -0,0 +1,23 @@
+/* Figures (with captions) */
+figure {
+ box-shadow: var(--ifm-global-shadow-lw);
+ border-radius: var(--ifm-global-radius);
+ border: var(--ifm-global-border-width) solid var(--unleash-color-gray);
+ padding: var(--ifm-pre-padding);
+ margin-inline: 0;
+}
+
+figure img {
+ box-shadow: none;
+ border: none;
+}
+
+figure * + * {
+ margin-block-start: var(--ifm-pre-padding);
+}
+
+figcaption {
+ font-size: var(--unleash-font-size-smaller);
+ padding-inline: var(--ifm-pre-padding);
+ border-inline-start: 5px solid var(--ifm-color-primary);
+}
diff --git a/website/src/css/custom.css b/website/src/css/custom.css
index 2a2d2b861b..398c47b3e5 100644
--- a/website/src/css/custom.css
+++ b/website/src/css/custom.css
@@ -13,6 +13,8 @@
--ifm-code-font-size: 90%;
--ifm-font-size-base: 15px;
--navbar-link-color: #122d33;
+
+ --unleash-font-size-smaller: 90%;
}
footer {
diff --git a/website/static/img/anatomy-of-unleash-constraint.png b/website/static/img/anatomy-of-unleash-constraint.png
new file mode 100644
index 0000000000..44dd2fe01e
Binary files /dev/null and b/website/static/img/anatomy-of-unleash-constraint.png differ
diff --git a/website/static/img/anatomy-of-unleash-customer-tiers.png b/website/static/img/anatomy-of-unleash-customer-tiers.png
new file mode 100644
index 0000000000..f91ac2badf
Binary files /dev/null and b/website/static/img/anatomy-of-unleash-customer-tiers.png differ
diff --git a/website/static/img/anatomy-of-unleash-environment.png b/website/static/img/anatomy-of-unleash-environment.png
new file mode 100644
index 0000000000..998267a684
Binary files /dev/null and b/website/static/img/anatomy-of-unleash-environment.png differ
diff --git a/website/static/img/anatomy-of-unleash-environments-strategies.png b/website/static/img/anatomy-of-unleash-environments-strategies.png
new file mode 100644
index 0000000000..2d9c6eaea8
Binary files /dev/null and b/website/static/img/anatomy-of-unleash-environments-strategies.png differ
diff --git a/website/static/img/anatomy-of-unleash-environments-strategies2.png b/website/static/img/anatomy-of-unleash-environments-strategies2.png
new file mode 100644
index 0000000000..3de4404d97
Binary files /dev/null and b/website/static/img/anatomy-of-unleash-environments-strategies2.png differ
diff --git a/website/static/img/anatomy-of-unleash-features.png b/website/static/img/anatomy-of-unleash-features.png
new file mode 100644
index 0000000000..7faffeae6e
Binary files /dev/null and b/website/static/img/anatomy-of-unleash-features.png differ
diff --git a/website/static/img/anatomy-of-unleash-new-feature-rollout.png b/website/static/img/anatomy-of-unleash-new-feature-rollout.png
new file mode 100644
index 0000000000..354d160328
Binary files /dev/null and b/website/static/img/anatomy-of-unleash-new-feature-rollout.png differ
diff --git a/website/static/img/anatomy-of-unleash-segments.png b/website/static/img/anatomy-of-unleash-segments.png
new file mode 100644
index 0000000000..d7be434b23
Binary files /dev/null and b/website/static/img/anatomy-of-unleash-segments.png differ
diff --git a/website/static/img/anatomy-of-unleash-strategy.png b/website/static/img/anatomy-of-unleash-strategy.png
new file mode 100644
index 0000000000..8a45aab019
Binary files /dev/null and b/website/static/img/anatomy-of-unleash-strategy.png differ
diff --git a/website/static/img/anatomy-of-unleash-variants.png b/website/static/img/anatomy-of-unleash-variants.png
new file mode 100644
index 0000000000..0684883093
Binary files /dev/null and b/website/static/img/anatomy-of-unleash-variants.png differ