help-centre-ui v1.0.1
Help Centre UI
A SSR Next application serving our help centre ui
Local Development
Prerequisites
You'll need yarn installed and working locally.
Once that's installed run yarn
within the project to install the dependencies
Commands
Here are the support commands:
Command | Description |
---|---|
yarn watch | Run the application locally in watch mode so it recompiles on saved changes |
yarn build | Build a production ready version of the application under a build directory |
yarn start | Start the compiled version of the application in the build directory |
yarn cypress:open | Start Cypress dashboard for the interactive test runner |
yarn cypress:headless | Start Cypress in a headless state |
yarn cypress:stub | Start the Cypress stub server |
yarn storybook | Start a local instance of Storybook |
yarn storybook:build | Build a static site version of the Storybook |
Infrastructure
Framework
This application is built with NextJS and React
Amongst many other perks this gives us:
- Server-rendering by default
- Automatic Code Splitting
- Simple Client Routing
Structure
The structure of our components follows those of Atomic Design utilising smaller components reused into larger abstract elements Read more here.
Typing
This project uses Typescript
Building dockerfile
Requirements
Running locally
docker-compose up
This will build, test the applicaiton before running on port 80 locally.
If you change your application code and want to re-build the image
docker-compose up --build
Environment Variables
Much like running the application straight from the project, you will need to provide the variables needed for the application to run. To do this, ensure your .env
file is present with the various details filled in.
Integration Testing
This project uses Cypress to automate the end to end testing. Read more about how to orchestrate Cypress tests here
Headless Mode
Running our integration tests in headless mode will trigger a test runner in ./cypress
and will also trigger a stub server to mock ssr calls.
Storybook
We use Storybook in our project for both development and hosting a catalogue of our components.
Find the catalogue here.
To create the look of our catalogue we're using addon-docs and governing the content through .mdx
files.
New pushes to master will trigger a re-build of the component static site and a Github Action will deploy this to github pages.
Feature Flags
Feature flag control is performed through Google's Firebase where we have two projects (non-prod and prod):
- digital-support-nonprod
- digital-support-prod
Upon app initalisation, the app queries Firebase, works out feature flag values (more on that in a sec), it then stores the value of the feature flags in the browsers local storage under the key _ff
. Data structure is stored as a string with the content being valid json with the key being the feature flag name and the value being a boolean.
Example of stored object structure:
{
"enabling_feature_flag": true,
"disabling_feature_flag": false
}
Working out feature flags
Straight boolean values
The most basic way to add a flag is a normal boolean value in remote config. In this situation any set values will be passed through as is.
JSON Flag Value
We also accept the follow data structure as a feature flag value:
{
"default": <boolean-value>,
[client]: <boolean-value>,
[client]: {
value: <boolean-value>,
percentage: <number-value>
}
[client]: {
value: <boolean-value>
}
}
Example:
{
"default": false,
"orion": {
"value": true,
"percentage": 10
},
"apollo": true
}
default value is required
In this example above the flag default would be false however 10% of orion traffic and 100% apollo traffic would get a true value for the feature flag.
Any incorrect config for a flag is treated as a false value
Development
There is now a new postinstall step which creates a featureFlag.json
file in the root of the project. When running in development mode this file is used in replacement for querying firebase.
This file should be a simple key value pair json file where the key is the name of the feature flag:
{
"enabling_feature_flag": true,
"disabling_feature_flag": false
}
Development mode is used by default when using the yarn watch
command.
Rendering elements based on feature flag
Do not put feature flags in the base of the page (with the ./page
directory - this will cause a full page reload
There is a component named FeatureFlaggedComponent which is there for easy use with feature flags:
const ExperimentalView = () => <p>ExperimentalView</p>;
const FallbackView = () => <p>FallbackView</p>;
...
<FeatureFlaggedComponent
featureFlag="featureFlagKey"
fallback={FallbackView()}
>
{ExperimentalView()}
</FeatureFlaggedComponent>
The component will query the flags, where featureFlagKey flag is true then we'd see the ExperimentalView be rendered, if it's false we'd see the FallbackView rendered.
Feature Flag Analytics
When a feature flag is in use a cookie is added to the clients browser session under the ID experiments
this cookie is a comma separated string containing feature flag keys and whether it's active with an appended Active
or Inactive
.
This active suffix is created when either the child or fallback is selected. If a flag is changed for a user then the old value is removed before adding the new value.
For instance:
A user has two feature flags avaliable, flagOne is currently true and flagTwo is currently false. When components are rendered the experiments cookie will have the value flagOneActive,flagTwoInactive,
.
Cookie instances have a shelf life of one hour.
4 years ago