I'm building an application that is used by multiple organisations. Each organisation accesses the application at their own sub-domain E.G. google.myapp.com
, microsoft.myapp.com
. They are all consuming the exact same bundle however, there is not a separate version running on each subdomain.
Some of the app styles are customised based on the branding of the organisation. Currently, a global class name is set based on the subdomain in the URL, and this applies styles to certain elements that need to change colour etc.
My setup is a React application running on a modified version of the create-react-app
webpack config.
What I'm trying to achieve is a setup where each organisation has a 'theme' mostly consisting of different SCSS variables. These variables will change core colours in the application.
I also have certain elements that need to be shown based on which organisation is viewing the app (navbar elements etc). I'd like the build only to have the relevant CSS for each organisation in the bundle.
I know this is a really broad question but I really don't know the best way to structure this. Any advice much appreciated!
I ended up migrating my application to styled-components and implementing a theme.
I store the main variables for each tenant in a theme object:
export const themes = {
tenantOne: {
primaryOne: COLOURS.wallop,
primaryTwo: COLOURS.wallop,
logoBackground: COLOURS.wallop,
secondaryOne: COLOURS.lostForest,
secondaryTwo: COLOURS.darkPurp,
[...]
},
tenantTwo: {
primaryOne: COLOURS.red,
primaryTwo: COLOURS.orange,
logoBackground: COLOURS.darkerGrey,
secondaryOne: COLOURS.darkerGrey,
secondaryTwo: COLOURS.darkerGrey,
[...]
},
};
Then I wrapped my application in the <ThemeProvider>
component supplied by styled-components
. I passed a function to the theme
prop which works out which tenant is using the app (with an ID fetched from the backend) and then returns the theme object to use.
<ThemeProvider theme={ platformBrandingHelper.getPlatformTheme(appId) }>
<App />
</ThemeProvider>
The helper function:
function getPlatformTheme(appId) {
switch (appId) {
case 'tenantOne':
return THEMES.tenantOne;
case 'tenantTwo':
return THEMES.tenantTwo;
default:
return THEMES.default;
}
}
From there on out it's just a case of styling your app using the variables in your theme as opposed to hard coding colours. This is why I migrated to styled-components
Example:
const Button = ({
className,
type,
onClick,
disabled,
active,
children,
}) => (
<button
disabled={ disabled }
className={ `${ className } ${ active ? 'active' : '' }` }
type={ type }
onClick={ (e) => onClick(e) }
>
<span className="content">
{ children }
</span>
</button>
);
const StyledButton = styled(Button)`
border-color: ${ (props) => props.theme.primaryOne };;
background: ${ (props) => props.theme.primaryOne };;
color: ${ (props) => props.theme.baseSix };
`;
Now the application will load the correct theme object for each tenant, then every component will be styled using the appropriate colours etc because they all rely on the variables passed to them from the theme.