The App/brands
directory is special in a way that it's the main building block in the whitelabel solution.
This document describes how the whitelabel mechanism affects the development of an app and how to approach various scenarios of differences between brands.
If you're after explanation of how the whitelabel mechanism works behind the scenes, see the mechanics document.
.env
file exists and has theENVKEY
variable set which points to a desired sub-environment from EnvKey app.
- Change the value of the
ENVKEY
in the.env
file to point to the desired brand. - Run
yarn configure-brand
. It will:- (re)generate
tsconfig.json
file with correct paths for the given brand, - make sure that only required native assets (e.g. fonts) are linked. It uses react-native-asset lib for this, so you don't need to worry about manually unlinking/removing anything,
- set the branded bundle ID and app name for iOS project,
- copy branded app icons to both android and iOS projects.
- (re)generate
- Stop the Metro bundler (if you have it running) and re-start it with
yarn start --reset-cache
. It will reset the "transform cache" forcing the full rebuilt of the app dependencies (which is needed for the brand change to take effect). - Make sure your VS Code is aware of the brand change by trigerring the
TypeScript: Restart TS server
command from the command pallete (cmd + shift + P
). It will reload thetsconfig.json
file (which got re-generated by the previous step) into the IDE runtime and ensure module imports are clickable and resolve correctly.
- Not every component needs to be branded. There may be cases where exactly the same (with same sets of props) is used for all supported brands and only CSS variables differ. In such case the components can "live" only in
App/components
(fully outside of the branded stuff). - All components in
App/components
should be considered as generic and be parameterised via props so that they can become branded in the future if such need arise. - For each component that is branded, the main implementation with all of the business logic and rendering resides in
App/components
and exposes various props which can be used for customisations. Only thin "wrappers" are placed under theApp/brands/<brand>/*
and each wrapper passes different set of props to the main one, making it look or behave different. We want to limit the code duplication and maximise code re-use. - It is possible to have only one brand having a specific branded version of the component. Others, which don't explicitly specify it, will use the one from the
default
brand. - The above means that whenever a component becomes branded for at least one brand. There always needs to be a corresponding one in the
default
brand. - The whitelabelling mechanism is flexible enough to cater for only selective components to be branded in the component hierarchy tree. Example:
Home (generic) ├─ HeroBanner (branded) ├─ ComplexComponent (generic) │ ├─ SubComponent (branded) | | └─ ChildComponent (generic) │ └─ AnotherSubComponent (generic) ├─ SimpleComponent (branded) └─ AnotherSimpleComponent (generic)
- In an edge-case, a branded component can return empty content. Resulting in given component to be totally hidden for the given brand.
Below paragraphs talk about how best to approach given "type" of difference between brands that needs to be handled.
These should be mostly abstracted as styling variables to avoid duplicating whole Style components. This is something still to be done in this project ;)
React Native StyleSheet
should be used and treated as a standalone ES module (not embedded in the components themselves).
This way it's possible to customise only styles without the need to make the whole component branded (in case there are no rendering or behaviour differences to handle).
The type of graphical assets this paragraph talks about are icons and graphics used within the apps. Mostly svg and png files. These types of assets should be exported as ES modules so the same whitelabelling rules will apply as with JS/TS components.
The concept of sub-environments in EnvKey is leveraged and there's one main/full set of config params (representing the default
brand) for the given environment and then a sub-env exists for each brand to overwrite only selected variables which need to be different between brands. Example could be bundle ID and app name, and the APP_BRAND value itself.
These will require given component to become "branded". The main implementation stays in the App/components
and exposes additional props which, wwhen passed different values, enable that main components to look or behave differently.
Thin branded wrappers are put in the App/brands/<brand>/*
folder and each wrapper includes the main coomponent, but passes a bit different set of props as needed.
These can be handled similarly to the rendering differences, but would be more adequate to bigger, composite, components, not so much to the small ones.
In case when you need to add an additional new brand, these are the steps required to set it up:
-
Create new sub-environments in EnvKey (one per each "main" environment)
- override at least the following variables in these sub-environments:
APP_BRAND
,BUNDLE_ID
,DISPLAY_NAME
.
- override at least the following variables in these sub-environments:
-
Create new folder under the
App/brands
directory with a name that matches whatever you set as the value ofAPP_BRAND
in EnvKey and add the following to it:
The above is the minimum required set-up for a new brand. After that you can start adding branded TS components to the App/brands/<brand>/*
and override more configuration variables in the given sub-environment in EnvKey.