How I added whitelabel theming to my Ember app

A need arose in my current EmberJS project to style the application differently for different instances of the app. Colors, logos, button styles, etc needed to be different but it still needed to be the same code base.

After an extensive DuckDuckGo search I found that there apparently wasn’t much of a need for this, and if there is, then its not documented well. Hence this story…

Configuring the SASS

My first idea on how to have multiple themes in one app was to add a themes folder to app/styles and have theme1.scss and theme2.scss that included the color variables and any other overrides that were necessary, and then somehow do a conditional import in app/styles/app.scss to use whatever theme was needed based on a variable. Since the ember build script automatically transpires app.scss.

I quickly learned that this is not possible in SASS, you cant use @import inside an @if in SASS (unfortunately). So handling this in SASS wasn’t an option.

Next, I tried importing app.scss into each of the theme files AFTER declaring the color variables. However, since ember attempts to transpile app.scss automatically, it errors because the color variables are not declared. Which makes sense, since I was setting colors in each of the theme files and importing app.scss to complete the stylesheet, but app.scss never knew about colors, so it failed.

I realized that I would have to NOT use app.scss because ember looks for it automatically, but I still wanted one file to handle most of the imports I had for foundation, pod component styles, and for some other stylesheets for pages.

So I created app/styles/main.scss copy/pasted the contents of app.scss and then imported main.scss in the theme files after the color variables.

Setup environment variable

The next step was to tell Ember what stylesheet to use based on an environment variable. I host ember apps on heroku.com, so all I needed to do was add a configuration variable of theme on each instance of the app to dictate which theme was used. Since heroku knows my app is a NodeJS app it will set these variables when Node is started.

Now that NodeJS knows what theme the instance wants, we need to tell Ember about it. To do this, I added an environment variable to the config file. Note the theme property. This is telling the config to go out and fetch a runtime environment variable from the Node process.

// ./config/environment.jsvar ENV = {
modulePrefix: 'my-app-name',
environment: environment,
rootURL: '/',
theme: process.env.theme,
locationType: 'auto',
EmberENV: {
...
}
}

Now the theme property is available anywhere we import the environment configs. From there, I imported the config/environment.js file into ember-cli-build.js so the build knew which theme to use.

Modifying the build

Here, the config file is imported and the environment is passed in from EmberApp as an argument.

// ember-cli-build.js
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
const ENV = require('./config/environment')(EmberApp.env());

EmberCLI has an option to override the outputPaths. More about that here. I used this option to customize where the CSS is compiled and what SASS file to use. So if the theme variable is some-theme then the path would be app/styles/themes/some-theme/main.scss and it would be compiled to assets/theme.css.

// ember-cli-build.js
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
const ENV = require('./config/environment')(EmberApp.env());
let theme = {};
theme[`themes/${ENV.theme}/main`] = `/assets/theme.css`;
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
// Add options here
outputPaths: {
app: {
css: theme
}
}
});
return app.toTree();
};

Change CSS link in HTML

The last thing to do is to reference a different CSS file in index.html.

<link integrity="" rel="stylesheet" href="
{{rootURL}}assets/theme.css">

Now, instead of my-app-name.css we import the theme thats built from our customized ember-cli-build options.

Thats it!

So, there you have it. Thats how I handled using multiple whitelabel themes across multiple instances of an ember app. Now, I realize that not everyone has the same needs such as whitelabeling across different instances or host.

But hopefully from this poorly written post about using NodeJS environment properties and EmberCLI options you can figure out a solution for your theming needs as well!

Cheers!

Simeon Berns 🇺🇸

Written by

Husband and father. Software developer. Esports enthusiast and Overwatch try hard. I love open source software and also stickers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade